(六)Git后悔药 - git revert 命令的使用
与 git reset 不同的是,git revert 不会修改提交历史,而是创建一个新的提交来反转之前的提交。
文章目录
1. 命令概述
git revert 命令用于创建一个新的提交,这个新提交的内容会抵消(反转)指定提交所引入的更改。
核心理解:
- 它不是“删除”历史提交,而是通过新增一个“反操作”的提交来达到撤销效果。
- 因此,它不会重写项目历史,这对于已经推送到远程仓库的提交来说是安全的,是团队协作中推荐的撤销方法。
- 你可以把它想象成一次“代码层面的撤销”,而不是“时间层面的回退”。
与 git reset 的对比:
这是理解 git revert 的关键。
| 特性 | git revert |
git reset (–hard) |
|---|---|---|
| 历史记录 | 保留被撤销的提交,并新增一个反转提交。 | 移除目标提交之后的所有提交,重写历史。 |
| 安全性 | 安全,适用于已推送的公共提交。 | 危险,仅适用于本地未推送的提交。 |
| 操作对象 | 工作目录和暂存区不受直接影响(通过新提交影响)。 | 直接移动 HEAD、暂存区和工作目录。 |
| 适用场景 | 撤销公共分支上的某个特定提交。 | 丢弃本地未提交的更改或撤销未推送的本地提交。 |
2. 命令格式
最基本的命令格式如下:
git revert [<选项>] <提交号>
<提交号>: 可以是完整的 commit hash,也可以是简短的 hash、分支名、标签名或HEAD指针等。例如a1b2c3d、HEAD~1、feature-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表示合并提交的第一个父提交,通常这是接收合并的分支(例如main或master)。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. 注意事项
- 冲突是常态:
- 当你尝试撤销一个很久以前的提交时,代码可能已经发生了翻天覆地的变化,Git 很可能无法自动应用“反操作”,这时就会产生冲突。
- 如何处理冲突?
- Git 会暂停 revert 过程。
- 你需要手动解决所有标记为冲突的文件。
- 使用
git add <文件名>将解决后的文件标记为已解决。 - 最后,执行
git revert --continue来完成这次 revert 操作。 - 如果想放弃本次 revert,可以执行
git revert --abort。
-
撤销一个“撤销”: - 因为
git revert是创建新的提交,所以你可以再次使用git revert来撤销这个“反转提交”本身。这相当于重新引入了最初被撤销的更改。 -
理解 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 <合并提交>来撤销合并 -> 推送。
- 场景1(撤销公共提交): 发现
-
清晰的信息: 为 revert 提交编写清晰的提交信息,说明为什么要撤销,以及撤销了哪些功能,这对于团队协作和历史追溯非常重要。
更多推荐
所有评论(0)