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 reset | git 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 进行授权