在软件开发中,执行命令时的“手抖”可能会导致灾难性的后果:误删了还在开发中的分支、错误的 reset --hard 抹掉了昨晚的加班成果,或者是合并冲突搞乱了整个代码库。
幸运的是,Git 几乎从不真正删除数据。它更像是一个具有完美记忆力的黑匣子。只要你曾经提交过,或者只是把代码 add 到了暂存区,Git 都有办法帮你找回来。
一、 终极自救神器:git reflog
如果说 git log 是查看项目的“官方历史”,那么 git reflog 就是 Git 的**“全记录黑匣子” 。它记录了本地仓库中 HEAD 指针的每一次**移动。
-
场景:你执行了
git reset --hard HEAD~1,结果发现删错提交了。此时git log已经看不到那个提交了。 -
救命操作:
- 输入
git reflog。 - 找到
reset操作之前的那个哈希值(通常标记为HEAD@{1})。 - 执行
git reset --hard <hash>,瞬间回到过去。
- 输入
二、 git reset 的三级防御
理解 reset 的不同粒度,能让你在撤销操作时更加精准。
-
--soft(轻度后悔) :- 效果:只撤销 Commit,不触动暂存区(Index)和工作区。
- 用途:你刚 Commit 完发现漏了一个文件,或者是想重新修饰一下提交信息。
-
--mixed(默认,中度后悔) :- 效果:撤销 Commit 和暂存区,保留工作区。
- 用途:你想把刚才的一堆乱七八糟的
add全部重来,但不想丢掉写的代码。
-
--hard(重度后悔/危险) :- 效果:彻底重置工作区到某个提交。
- 警告:这会抹掉所有未提交的修改。执行前务必确认。
三、 git revert:“体面”撤销
在公司的共享分支(如 master 或 develop)上,严禁使用 reset 来撤销已经推送的提交,因为这会破坏其他人的历史。
- 方案:使用
git revert <commit-hash>。 - 原理:它不会删除旧提交,而是创建一个完全相反的新提交。比如旧提交增加了 10 行代码,Revert 提交就会删除这 10 行。
- 优势:历史记录是完整的,所有人都能清晰地看到:由于某种原因,某次发布被“冲抵”了。
四、 紧急避险:git stash
有时候你正在改一个复杂的 Bug,突然接到通知要切换到 hotfix 分支修线上事故。此时你的代码改了一半,逻辑还是碎的,不能 Commit,怎么办?
- 操作:执行
git stash。 - 效果:Git 会把当前工作区和暂存区的修改“藏”进一个栈里,让你的工作区瞬间变干净。
- 回来后:执行
git stash pop,代码原样恢复。
五、 找回“从未提交”的代码?
这是最极端的情况:你写了代码,执行了 git add,但还没 commit 就被误删了文件。
- 黑科技:
git fsck --lost-found。 - 逻辑:只要你
add过,文件内容就已经变成了.git/objects里的 Blob 对象。虽然没有 Commit 指向它,但它还躺在磁盘上。这个命令会帮你把这些“孤儿对象”找出来,存放在.git/lost-found目录下。
💡 总结
在 Git 的世界里, “提交”就是保存点。作为一名资深开发者,养成“小步快跑、频繁提交”的习惯(哪怕后期再用 rebase 合并),是你给自己买的最好的“保险”。