文章

git-revert

生成新提交,撤销指定提交的修改,安全撤销历史。

git-revert

git revert

git revert <commit> 的作用是:创建一个“反向提交”,撤销指定提交的更改,但保留原有历史

它不会改写历史,而是在当前 HEAD 上追加一个反向修改的新提交,这是它与 git reset 最大的区别。

reset 的根本区别

命令是否改写历史?是否保留历史记录?是否适合多人协作(远程分支)?
git reset✅ 会改写❌ 会丢弃之后的提交❌ 不推荐
git revert❌ 不改写✅ 所有提交都保留✅ 非常安全

实例演示

假设提交历史如下:

1
A -- B -- C -- D (main)

想撤销提交 C

1
git revert C

结果变成:

1
A -- B -- C -- D -- E (main)

其中:

  • E 是 Git 自动生成的一个反向提交,它的效果是「把 C 做的事反过来」;
  • 历史不会断裂,也不会改变任何提交 ID;
  • 适合远程协作、线上代码回滚等场景。

基本命令格式

1
git revert <commit>

常见变体:

命令功能
git revert HEAD撤销最近一次提交
git revert HEAD~2撤销倒数第 3 次提交
git revert a1b2c3d撤销某个具体提交
git revert --no-commit <commit>创建反向更改,但不提交(类似 --soft

什么是“反向提交”

假设某次提交 C 改了 file.txt 内容如下:

1
2
- int x = 1;
+ int x = 2;

那执行 git revert C 生成的新提交会做:

1
2
- int x = 2;
+ int x = 1;

本质上是:基于 C 的 diff,生成一个“反向 diff”并作为新提交记录下来

多个提交一起回滚

可以这样:

1
git revert A..D

含义是:A(不含)到 D(含)这些提交依次反转

或:

1
git revert C D

多个提交逐个反转。

注意:

  • 多次 revert 可能导致冲突;
  • 建议加 --no-commit 自己处理冲突后再手动提交。

常见选项

选项含义
--no-commit执行反转但不自动提交
--edit(默认)打开编辑器修改 commit 信息
--no-edit不打开编辑器,直接使用默认信息
--mainline <n>用于revert 合并提交,指定主分支父节点(较复杂)

特别注意:revert 合并提交

1
git revert -m 1 <merge-commit-id>

其中 -m 1 表示使用第一个父提交作为“主线”,只撤销合并带来的差异。

合并提交结构复杂,不建议轻易 revert,除非你明确知道合并时的父子结构。

推荐使用场景

场景是否推荐用 revert
线上分支出 bug,要撤销提交✅ 强烈推荐
本地提交还没推送❌ 用 reset 更合适
团队协作,不能改历史✅ 必须用 revert
想保留历史但取消效果✅ 用 revert

示例操作

1
2
3
4
5
6
7
8
git log --oneline
# 输出:
# f123456 修复登录bug
# e789abc 添加登录表单
# d456def 初始化项目

git revert e789abc
# 生成一个新提交,反转“添加登录表单”的更改

总结对比:git revert vs git reset

特性git resetgit revert
是否改历史✅ 会❌ 不会
是否保留提交记录❌ 不会✅ 会
是否适合团队协作❌ 否✅ 是
典型用途回退本地提交安全撤销线上提交
是否可恢复一定条件下可用 reflog永远保留历史

命令速查表

操作命令
撤销最近提交git revert HEAD
撤销某个提交git revert <commit-id>
撤销多个提交git revert A..D
只反转但不提交git revert --no-commit <commit>
回滚合并提交git revert -m 1 <merge-commit>
本文由作者按照 CC BY 4.0 进行授权