⏪ 第六章:撤销与回退 —— 后悔药指南
⚠️ 注意: 这一章涉及一些危险操作。在学习之前,请记住一个铁律:已经 push 到远程仓库的提交,不要轻易修改,否则你的队友会找你"聊天"的。
git restore—— 丢弃工作区的修改
bash
# 场景:小明修改了 index.html,但觉得改坏了,想回到上次提交的状态
# 先看看改了什么
git diff index.html
diff --git a/index.html b/index.html
--- a/index.html
+++ b/index.html
@@ -4,5 +4,5 @@
<title>我的第一个网站</title>
</head>
<body>
- <h1>Hello, Git!</h1>
+ <h1>这个标题被我改坏了</h1>
</body>
# 丢弃这个文件的修改
git restore index.html
# 验证:修改已经没了
git diff index.html
(空输出,说明没有差异)📝 备注: git restore是 Git 2.23+ 新增的命令,比旧的git checkout -- <file>更直观。这个操作不可撤销,修改的内容会彻底消失(正常情况下无法找回,但专业数据恢复工具可能有办法)。三思而后行!
git restore --staged—— 从暂存区撤回
bash
# 场景:小明把 style.css 添加到了暂存区,但突然想撤回
git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: style.css
# 从暂存区撤回(文件修改保留,只是取消暂存)
git restore --staged style.css
git status
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: style.css简单吧?git restore 丢弃工作区修改,git restore --staged 只取消暂存但保留修改。记住这个区别就不会搞混了。
git reset—— 回退提交(三种模式)
git reset 是一个非常强大的命令,但也有三种不同的"力度",就像橡皮擦有三种硬度:
Soft Reset —— 只回退提交,保留暂存区和工作区
bash
# 回退一个提交,但修改保留在暂存区
git reset --soft HEAD~1
# 适用场景:提交信息写错了,想重新写
git reset --soft HEAD~1
git commit -m "fix: 正确的提交信息"Mixed Reset(默认)—— 回退提交和暂存区,保留工作区
bash
# 回退一个提交,暂存区也清空,但工作区的修改还在
git reset HEAD~1
# 等同于
git reset --mixed HEAD~1
# 适用场景:想重新组织哪些文件应该放在一个提交里Hard Reset —— 全部回退,修改消失!
bash
# ⚠️ 危险操作!所有未提交的修改都会消失!
git reset --hard HEAD~1
HEAD is now at a1b2c3d feat: 创建首页,Hello Git!⚠️ 注意: ⚠️--hard是核弹级别的操作!它会彻底丢弃所有未提交的修改,无法通过git restore恢复。在使用前,请确保你真的不需要那些修改了。如果只是想"让分支指向另一个提交",考虑用git revert更安全。
| 模式 | 提交历史 | 暂存区 | 工作区 |
|---|---|---|---|
| --soft | 回退 ✗ | 保留 ✓ | 保留 ✓ |
| --mixed | 回退 ✗ | 回退 ✗ | 保留 ✓ |
| --hard | 回退 ✗ | 回退 ✗ | 回退 ✗ |
git revert—— 安全地"撤销"提交
如果 git reset 是时光倒流(修改历史),那 git revert 就是写一封"撤回邮件"——它不修改历史,而是创建一个新的提交来"抵消"之前的提交。
bash
# 撤销最近一次提交
git revert HEAD
[main c3d4e5f] Revert "feat: 添加欢迎语"
1 file changed, 1 insertion(+), 1 deletion(-)
# 查看历史,注意 revert 提交还在
git log --oneline
c3d4e5f (HEAD -> main) Revert "feat: 添加欢迎语"
f4e5d6c feat: 添加欢迎语
b2c3d4e feat: 添加基础样式
a1b2c3d feat: 创建首页,Hello Git!💡 提示: 对于已经 push 到远程的提交,永远用git revert而不是git reset。因为 revert 不会改变历史,你的队友不会受到影响。
git reflog—— 最后的救命稻草
如果说 Git 是时光机,那 reflog 就是时光机的操作日志——它记录了 HEAD 指针的每一次移动。
bash
# 场景:小明手抖执行了 git reset --hard,把修改全删了!
# 别慌!先看 reflog
git reflog
a1b2c3d (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
f4e5d6c HEAD@{1}: commit: feat: 添加欢迎语
b2c3d4e HEAD@{2}: commit: feat: 添加基础样式
a1b2c3d HEAD@{3}: commit (initial): feat: 创建首页,Hello Git!
# 找到你想要恢复的那个提交
# f4e5d6c 就是"添加欢迎语"那次提交
# 恢复到那个状态!
git reset --hard f4e5d6c
HEAD is now at f4e5d6c feat: 添加欢迎语
# 修改回来了!📝 备注: reflog默认保留 90 天的记录。只要在这 90 天内,几乎任何"手抖"操作都可以恢复。这就是 Git 的安全网。