Git 的五个"后悔药":什么时候用 restore、reset、revert、reflog

举报
yd_251777447 发表于 2026/11/02 18:56:40 2026/11/02
【摘要】 删错了文件、提交错了分支、把别人的改动覆盖了——这些事谁都干过。Git 的好处是几乎每一步都能退回去,坏处是"怎么退"有五六种写法,选错了会把事情变得更糟。 这篇把五个常用的恢复手段理清楚,顺便说清哪个是真正危险的。 一、 git restore :撤销工作区的修改 最常见的需求:改了几个文件,发现方向不对,想全部丢掉。 注意最后一个: staged 只动暂存区,文件内容不变。

删错了文件、提交错了分支、把别人的改动覆盖了——这些事谁都干过。Git 的好处是几乎每一步都能退回去,坏处是"怎么退"有五六种写法,选错了会把事情变得更糟。

这篇把五个常用的恢复手段理清楚,顺便说清哪个是真正危险的。

一、git restore:撤销工作区的修改

最常见的需求:改了几个文件,发现方向不对,想全部丢掉。

# 丢弃工作区里某个文件的修改
git restore path/to/file.js

# 丢弃所有未暂存的修改
git restore .

# 取消暂存(把文件从暂存区拿出来,但保留修改)
git restore --staged path/to/file.js

注意最后一个:--staged 只动暂存区,文件内容不变。很多人习惯用 git reset HEAD 做同样的事,效果一样,但 restore 语义更清楚——它只管恢复,不牵扯提交历史。

危险等级:中。 丢弃的修改没有进过 Git,找不回来。执行前先 git status 看一眼,或者干脆 git stash 存一下。

二、git reset:撤销提交,三种模式差别很大

这是最容易用错的一个。三个参数的行为完全不同:

| 参数 | 提交历史 | 暂存区 | 工作区 |

|---|---|---|---|

| --soft | 回退 | 保留 | 保留 |

| --mixed(默认) | 回退 | 清空 | 保留 |

| --hard | 回退 | 清空 | 清空 |

# 撤销最近一次提交,改动仍在暂存区,可以直接重新提交
git reset --soft HEAD~1

# 撤销提交并取消暂存,改动还在工作区,可以重新挑选要提交的部分
git reset HEAD~1

# 彻底丢弃这次提交及其所有改动
git reset --hard HEAD~1

日常用得最多的是 --soft 和默认的 --mixed:提交信息写错了、少加了文件、提交粒度太粗,都靠它们重来。

危险等级:--hard 是真正危险的。 它会连工作区的改动一起抹掉,而且这些改动从来没被 Git 记录过。用之前一定确认:这次的改动里有没有还没提交、也没别处备份的东西。

还有一点:reset 会改写历史。如果是已经推到远端的提交,reset 之后必须 push --force,而 force push 会影响所有基于这些提交工作的人。团队协作时这一条几乎是红线。

三、git revert:安全的"反向提交"

如果提交已经推到共享分支,正确做法不是 reset,而是 revert:

# 生成一个新提交,内容正好抵消指定提交的改动
git revert <commit-hash>

它不删除历史,只是在末尾追加一次反向操作。历史保持完整,别人拉代码不会冲突。

代价是历史里会留下"提交—撤销"两条记录。对于已经公开的提交,这个代价是值得付的。

判断标准很简单:这个提交别人拉过没有? 拉过就用 revert,没拉过才考虑 reset。

四、git reflog:找回"已经消失"的提交

reflog 记录的是本地 HEAD 的每一次移动,包括那些已经被 reset 掉的提交。它是撤销操作的最后一道保险。

# 看最近的操作记录
git reflog

# 输出大致长这样
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# e4f5g6h HEAD@{1}: commit: 添加用户导出功能

只要找到那一行,就能把提交捡回来:

git reset --hard e4f5g6h
# 或者
git cherry-pick e4f5g6h

reflog 默认保留 90 天(未引用的对象 30 天)。也就是说,误删的提交在大多数情况下都还在,只是不在任何分支上,普通 git log 看不见。

这是我个人觉得最值得记住的一条:手滑 reset --hard 之后,先别慌,先 git reflog。

五、git stash:临时挪开改动

改到一半要去修个紧急 bug,但当前改动还不适合提交:

# 存起来(含未跟踪文件要加 -u)
git stash push -u -m "重构到一半"

# 看存了哪些
git stash list

# 恢复最近一次(并从栈里删除)
git stash pop

# 恢复但保留在栈里
git stash apply

stash 的坑在于它很容易被遗忘。存了五六个栈,过一周完全不记得哪个是哪个。所以养成带 -m 写说明的习惯,比事后翻 diff 强得多。

危险等级:低,但容易"存了等于丢了"。 stash 里的东西不在任何分支上,git log 看不到。不过它同样能被 reflog 找回(git fsck --unreachable 也能捞)。

六、一张判断表

真出问题时,按这个顺序判断:

| 你想做什么 | 用什么 | 危险点 |

|---|---|---|

| 丢掉工作区修改 | git restore . | 改动不可恢复 |

| 撤销提交、保留改动 | git reset --soft HEAD~1 | 安全 |

| 彻底丢弃提交和改动 | git reset --hard | 高危,先 git status |

| 撤销已公开的提交 | git revert | 安全,历史留痕 |

| 找回被 reset 的提交 | git reflog | 90 天内大概率还能救 |

| 临时挪开改动 | git stash -u -m "说明" | 记得写说明 |

七、小结

三句话能概括:

没提交过的改动,只有 stash 和备份能救;提交过的改动,reflog 几乎总能救;已经公开的提交,只能用 revert 而不能 reset。

真正需要小心的只有 reset --hard 和 push --force 这两个。其余的操作,只要提交进过仓库,基本都有退路。

养成一个习惯就好:做任何"可能删东西"的操作之前,先跑一次 git status,再看一眼 git log --oneline -5。 十秒钟的成本,能省掉一次深夜的数据恢复。


文中命令基于 Git 2.x 实测。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。