git revert 适合撤销已推送到远程的提交,它创建反向新提交而不改写历史;git reset --hard 仅适用于未推送的本地提交;撤销中间某次提交需用 git rebase -i;处理合并提交需指定 -m 参数。

git revert 适合撤销已推送到远程的提交
如果目标提交已经 git push 到远程仓库,直接 git reset 会改写历史,可能破坏协作者的工作。此时必须用 git revert —— 它不删除原提交,而是创建一个“反向操作”的新提交,安全且可追溯。
操作很简单:
- 先查出要撤销的提交哈希(比如
abc1234):git log --oneline -n 10 - 执行:
git revert abc1234 - 保存自动生成的提交信息(默认是
Revert "xxx"),退出编辑器即可
注意:如果该提交引入了冲突(比如它删掉的文件在后续又被修改过),git revert 会中断并提示你手动解决,解决后 git add . && git revert --continue。
git reset --hard 只适用于未推送的本地提交
如果你确认该提交只在自己本地、还没 git push,且想彻底抹掉它(包括它引入的代码变更),git reset --hard 更直接。
关键不是“撤销”,而是“把 HEAD 和工作区一起回退到前一个提交”:
-
git reset --hard HEAD~1:撤销最近一次提交(含暂存区和工作区) -
git reset --hard abc1234^:撤销指定提交(^表示它的父提交) - 撤销后,用
git reflog还能找回(只要没被 GC 清理),但远程分支不会自动同步
⚠️ 切记:一旦执行 git reset --hard 后又 git push --force,就等于强行覆盖远程历史,除非你明确知道所有协作者都已处理完本地分支,否则不要碰。
撤销中间某次提交,但保留它之后的提交
这是最易出错的场景:你想删掉第 3 次提交,但保留第 4、5 次。不能简单 reset --hard,否则第 4、5 次也没了;也不能直接 revert,因为 revert 只生成反向提交,历史里仍存在那条记录。
正确做法是交互式变基(git rebase -i):
-
git rebase -i abc1234^(abc1234是你想删的提交哈希,^表示从它的父提交开始编辑) - 编辑器中把对应行的
pick改成drop或直接删掉那一行 - 保存退出,Git 会重放其余提交。如果有冲突,解决后
git add . && git rebase --continue
⚠️ 这本质是重写历史,等同于 reset 的风险级别。仅限本地未推送分支,或团队明确约定允许 force-push 的情况。
别混淆 revert 和 reset 的适用边界
很多人卡在“为什么我 revert 了,代码却没变回来?”——大概率是因为目标提交本身只是合并提交(merge commit),而 git revert 默认只处理第一个父提交。
遇到合并提交需显式指定主分支来源:
-
git revert -m 1 abc1234:撤销合并时“被合入”的那个分支的变更(常用) -
git revert -m 2 abc1234:撤销“发起合并”的分支的变更(少见)
另外,git revert 不支持撤销多个非连续提交(比如跳着选第 2 和第 5 条),必须逐条执行或改用 rebase -i。这点容易被忽略,直到报错才意识到。











