1. 命令概述

git revert 命令用于创建一个新的提交,这个新提交的内容会抵消(反转)指定提交所引入的更改
核心理解:

  • 它不是“删除”历史提交,而是通过新增一个“反操作”的提交来达到撤销效果。
  • 因此,它不会重写项目历史,这对于已经推送到远程仓库的提交来说是安全的,是团队协作中推荐的撤销方法。
  • 你可以把它想象成一次“代码层面的撤销”,而不是“时间层面的回退”。

git reset 的对比:
这是理解 git revert 的关键。

特性 git revert git reset (–hard)
历史记录 保留被撤销的提交,并新增一个反转提交。 移除目标提交之后的所有提交,重写历史
安全性 安全,适用于已推送的公共提交。 危险,仅适用于本地未推送的提交。
操作对象 工作目录和暂存区不受直接影响(通过新提交影响)。 直接移动 HEAD、暂存区和工作目录。
适用场景 撤销公共分支上的某个特定提交。 丢弃本地未提交的更改或撤销未推送的本地提交。

2. 命令格式

最基本的命令格式如下:

git revert [<选项>] <提交号>
  • <提交号>: 可以是完整的 commit hash,也可以是简短的 hash、分支名、标签名或 HEAD 指针等。例如 a1b2c3dHEAD~1feature-branch
  • [<选项>]: 常用的选项会在下面介绍。

3. 基本用法

3.1 撤销最近的一次提交

这是最常见的场景。

git revert HEAD
  • 这条命令会撤销最近一次提交(即 HEAD 指向的提交)引入的更改。
  • 执行后,Git 会打开默认的文本编辑器,让你编辑新生成的“反转提交”的提交信息。默认信息是 Revert “原提交信息”。你可以直接保存退出,也可以修改它。
  • 完成后,使用 git log --oneline 查看,你会发现多了一条新的提交记录。

3.2 撤销指定的某次提交

如果你想撤销历史中的某一次特定提交。

git revert a1b2c3d
  • a1b2c3d 替换为你想要撤销的提交的哈希值。
  • Git 会分析 a1b2c3d 这个提交所做的修改,然后创建一个新提交,将这些修改全部还原。

3.3 撤销一个连续的提交范围

你可以撤销从提交 A 到提交 B 之间的所有更改。请注意,这会为范围内的每一个提交都创建一个新的反转提交。

git revert <较早的提交号>..<较晚的提交号>
  • 范围是左开右闭(start, end]。它不会撤销“较早的提交号”本身,而是会撤销从“较早的提交号”之后,到“较晚的提交号”(包括它)之间的所有提交。
  • 例如,git revert HEAD~3..HEAD 会撤销最近的三次提交(不包括 HEAD~3,但包括 HEAD~2, HEAD~1, HEAD),并生成三个新的反转提交。

4. 高级用法

4.1 不打开编辑器,直接使用默认提交信息 (-n/–no-edit)

如果你不想在 revert 时打开编辑器确认提交信息,可以使用这个选项。

git revert -n a1b2c3d

4.2 撤销合并提交 (-m)

撤销一个合并提交 (merge commit) 比较特殊,因为合并提交有两个父提交。Git 需要知道你希望将分支回退到哪个父提交所代表的线上。

git revert -m 1 <合并提交的哈希号>
  • -m 1: 这个选项用于指定“主线”。1 表示合并提交的第一个父提交,通常这是接收合并的分支(例如 mainmaster)。2 表示被合并进来的分支(例如 feature-branch)。
  • 何时使用? 当你合并了一个功能分支后,发现这个功能有问题,想立刻撤销整个合并,就应该使用 git revert -m 1

**示例:**你刚刚将 feature/login 分支合并到了 main 分支,合并提交的 hash 是 m3rG3c0d3。现在想撤销这次合并:

git revert -m 1 m3rG3c0d3

4.3 连续撤销多个提交,但只生成一个反转提交 (-n + git commit)

当你使用范围 revert 时,默认会为每个被撤销的提交都生成一个反转提交。如果你希望所有这些撤销操作只生成一个提交,可以结合 -n 选项。

5. 注意事项

  1. 冲突是常态
  • 当你尝试撤销一个很久以前的提交时,代码可能已经发生了翻天覆地的变化,Git 很可能无法自动应用“反操作”,这时就会产生冲突
  • 如何处理冲突?
    1. Git 会暂停 revert 过程。
    2. 你需要手动解决所有标记为冲突的文件。
    3. 使用 git add <文件名> 将解决后的文件标记为已解决。
    4. 最后,执行 git revert --continue 来完成这次 revert 操作。
    5. 如果想放弃本次 revert,可以执行 git revert --abort
  1. 撤销一个“撤销”: - 因为 git revert 是创建新的提交,所以你可以再次使用 git revert 来撤销这个“反转提交”本身。这相当于重新引入了最初被撤销的更改。

  2. 理解 revert 的范围: - 记住 A..B 是左开右闭区间。如果你要撤销从提交 X 开始的所有提交,应该找到 X 的前一个提交 W,然后使用 git revert W..HEAD
    4

6. 总结与最佳实践

黄金法则: 对于已经推送到远程公共仓库的提交,永远使用 git revert。对于尚未推送的本地提交,可以使用 git reset

  • 工作流

    • 场景1(撤销公共提交): 发现 main 分支上一个已推送的提交有 bug -> 使用 git revert <坏提交> -> 解决可能的冲突 -> 推送新的反转提交到 main
    • 场景2(撤销合并): 合并了一个有问题的功能分支 -> 使用 git revert -m 1 <合并提交> 来撤销合并 -> 推送。
  • 清晰的信息: 为 revert 提交编写清晰的提交信息,说明为什么要撤销,以及撤销了哪些功能,这对于团队协作和历史追溯非常重要。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐