撤销三件套:reset / restore / revert 怎么选

三个命令都带「撤销」字眼,却作用在不同对象上。一句话:reset 动指针、restore 救文件、revert 改历史。下面按场景讲清楚该用哪一个。

最后更新:2026-10-29

Git 命令速查表 → Git 急救手册 →

三句话分清

下面先用一张表看全局,再按场景对号入座。

一句话对比

维度git resetgit restoregit revert
作用对象分支指针(提交历史)工作区 / 暂存区的文件提交历史(生成反向提交)
是否产生新提交否,改写历史否是
能否撤销已推送不推荐(改写共享历史)否(只动本地文件)是(推荐)
常见用途回退本地提交、整理历史丢弃未提交改动、恢复误删文件撤销已公开的提交
危险点--hard 会丢工作区改动方向指错会覆盖文件基本安全

该用哪一个?

# 记住一句口诀
# reset 动指针 / restore 救文件 / revert 改历史

git reset:移动分支指针

reset 的三个常用模式,区别在「动不动暂存区和工作区」:

git reset --soft HEAD~1   # 只移动指针;暂存区和工作区原样保留(适合重新提交)
git reset --mixed HEAD~1  # 默认模式;指针移动 + 暂存区清空(改动回到工作区)
git reset --hard HEAD~1   # 指针移动 + 暂存区和工作区都还原(工作区改动会丢失!)

注意:--hard 会丢掉工作区未提交的改动,且改写历史,只用于尚未共享的提交。后悔了?只要提交过,用 git reflog 仍能找回被移开的提交(详见急救手册)。

git restore:恢复文件

restore 专治「文件改乱了 / 删了 / 加错暂存区」,它不碰提交历史:

git restore README.md                 # 工作区文件恢复到最近一次提交的状态(丢弃改动)
git restore --staged app.js            # 只把文件移出暂存区,改动仍留在工作区
git restore --source=HEAD~1 app.js     # 把文件恢复到上一个提交时的内容

与 reset 不同,restore 默认只影响文件、不会移动分支指针,语义更清晰。Git 2.23+ 推荐用它替代 git checkout 的文件恢复用法。

git revert:安全地撤销已公开历史

revert 不改变任何已有提交,而是新建一个「反向」提交来抵消目标提交的效果:

git revert <commit>          # 撤销单个提交,生成一个新的反向提交
git revert HEAD~2..HEAD      # 撤销一段提交(按从旧到新逐个生成反向提交)

因为产生的是新提交,可以安全 push 到共享分支,队友拉取后历史依然连续。适合「线上出 bug,要紧急回滚但不想改写历史」的场景。

常见误区

常见问题

撤销之后提交记录还在吗?

取决于命令。git revert 一定保留(它新增一个反向提交);git reset --hard 会改写历史,但被移开的提交对象通常仍在本地 90 天内,可用 git reflog 找回;只有 reset --hard 之后又做了垃圾回收才会真正消失,这种情况很少见。

已经 push 的提交怎么撤销最安全?

用 git revert:它生成一个新提交来抵消旧提交的效果,可以正常 push 到共享分支,不会改写队友已经拉取的历史。绝对不要先 reset --hard 再 force push 去「抹掉」已共享的提交。

git restore 和 git checkout 有什么区别?

两者都能恢复文件,但 restore 语义更清晰:它只作用于文件,不会移动分支指针,也避免了 checkout 在「分支名」和「文件名」重名时混淆的情况。新版 Git 推荐用 restore 做文件恢复、用 switch 做分支切换。