用reflog恢复git reset --hard后的提交
这些代码块对应不同情况,不是一个完整脚本。请选择适合仓库的情况,并替换分支名、路径和VERIFIED_COMMIT。中止命令只适用于对应的正在进行的操作,不要执行两种备选方案。
简短答案
运行git reset --hard后,在reflog中查找之前的提交,核对内容,再创建恢复分支。前提是该提交对象仍然存在。
示例与前提
这套流程恢复已经提交的工作。只存在于工作目录、从未提交的编辑不会保存在reflog中。
修改前检查状态
先停止新的reset、rebase和分支切换。在移动引用之前,读取git reflog并通过git show检查内容。
git status --short
git reflog --date=iso
git show VERIFIED_COMMIT保留引用或独立检出
在VERIFIED_COMMIT上创建rescue/lost-work,为找到的提交保留一个引用,不改变当前分支,也不覆盖工作文件。
git branch rescue/lost-work VERIFIED_COMMIT
git log -5 --oneline rescue/lost-work第一种操作
检查恢复分支的历史和补丁。可以在另一个checkout中查看,或明确选择需要合并的修改。
有意选择另一种结果
直接reset到恢复的提交会再次改变分支、索引和文件。先保存当前修改,并建立恢复引用。
限制与例外
HEAD@{1}只是reflog中的位置,不保证就是正确提交。ORIG_HEAD可能保存之前的分支顶端,但其他操作可以覆盖它。
冲突与清理
reflog过期和对象清理遵循不同的可配置策略。即使旧记录还在,也无法重建已经删除的提交对象。
验证结果
核对恢复分支的提交、文件和历史。在整合修改之前运行相关测试。
git show --stat rescue/lost-work
git status --short常见问题
git revert创建反向提交,不会把分支移回reset之前。对于仅暂存的内容,git fsck有时能找到blob,但不保证文件名和目录结构。
在FluxGit中审查操作
FluxGit的Safety Timeline汇集reflog移动和恢复点。功能开启且检测到本地修改时,受保护的reset路径可以保存安全stash;教程中的普通终端reset没有使用这层保护。
Git官方文档
撤销 git reset --hard:找回丢失的提交
执行 git reset --hard 后,只要提交对象仍被保留,就可以通过本地 reflog 恢复已提交的更改。reflog 过期或对象被清理后,无法保证恢复。
在测试仓库中录制。
阅读旁白文字稿
- 你执行了 git reset --hard,最后一次提交不见了。这样的失误每个人都可能犯一次。下面介绍找回它的方法和原理。
- 首先,完成一项改动并提交:让支付调用重试两次。
- 然后,在终端中执行 git reset --hard HEAD~1。
- FluxGit 立即检测到了变化。分支退回到之前的位置,那次提交已不在该分支上。
- 为什么它没有丢失?分支只是指向提交的标签。reset 把标签移回之前的位置,但提交仍在仓库中,Git 的日记 reflog 也仍然记录着它。在这个提交上创建一个分支,就能找回它。
- FluxGit 中的 Recover lost work 用通俗的语言解释操作,并带你找到正确的位置。
- Safety Timeline 用一句话显示这次 reset。从 reset 之前的时刻创建一个分支。
- 你的提交回来了,位于它自己的分支上。
- 未提交的改动不在 reflog 中。启用恢复点并检测到本地改动时,FluxGit 可以在 hard reset 前保存一个安全 stash。本例在终端中直接执行普通 Git reset,绕过了这项保护。
- 在终端中也一样:运行 git reflog,找到 reset 之前的那一行,然后在对应的提交上创建一个分支。
- 总结:reset 移动标签,reflog 记住标签原来的位置。创建分支来保留提交。下一课:恢复已删除的分支。