使用Git实现revert的完整操作步骤

好的,我们来详细讲解如何使用 Git 的 revert 命令来撤销提交。revert 是 Git 中一个非常重要且安全的操作,尤其适用于已经推送到公共仓库的提交。

图片[1]_使用Git实现revert的完整操作步骤_知途无界

核心概念:Revert vs Reset

在深入步骤之前,必须理解 revertreset 的根本区别,这决定了你应该在何时使用它们。

特性git revertgit reset
作用创建一个新的提交,这个新提交的内容正好是撤销指定提交的更改。移动分支指针,将 HEAD 指向一个指定的旧提交,​丢弃之后的提交。
历史记录不修改历史。它向历史中添加了一个新的“撤销”记录,保留了完整的历史轨迹。重写历史。它会删除指定提交之后的所有提交,使历史看起来像从未发生过那些更改。
安全性安全。因为它不破坏历史,所以适用于已经推送(push)到远程仓库的提交。危险。因为它会重写历史,如果你已经推送了提交,强制推送(push -f)会给协作者带来极大的困扰。
适用场景撤销公共的、已经共享的提交。撤销本地的、尚未推送的提交,或者彻底丢弃最近的几个提交。

简单比喻​:

  • Revert​ 像是给一本书添加一个勘误页,说明“之前的第X页有误,正确内容应为Y”。书的历史(所有页码)都保留着。
  • Reset​ 像是直接撕掉书中的第X页到第Y页,然后重新装订。书的历史被改变了。

结论:对于已经推送到远程仓库的提交,请务必使用 git revert!​


​**git revert 的完整操作步骤**​

假设我们有以下的提交历史,最新的提交是 HEAD,我们想撤销 “Add feature Z” 这个提交。

* c3d4e5f (HEAD -> main) Add feature Z  <- 我们想撤销这个提交
* b2c3d4e Fix bug in feature Y
* a1b2c3d Implement feature Y
* 9876543 Initial commit

步骤 1:找到要撤销的提交的哈希值 (Hash)​

你需要知道要撤销的那个提交的标识(commit hash)。

  1. 使用 git log 查看提交历史。 git log --oneline 输出会类似于: c3d4e5f (HEAD -> main) Add feature Z b2c3d4e Fix bug in feature Y a1b2c3d Implement feature Y 9876543 Initial commit 我们要撤销的提交 Add feature Z 的哈希值是 c3d4e5f(通常只需前7位即可)。

步骤 2:执行 Revert 操作

使用 git revert 命令加上要撤销的提交的哈希值。

git revert c3d4e5f

步骤 3:处理 Revert 提交信息

执行命令后,Git 会立即打开你的默认文本编辑器(如 Vim 或 VSCode),让你编辑一个新提交的提交信息。

默认提交信息是:

Revert "Add feature Z"

This reverts commit c3d4e5f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.
  • 第一行是自动生成的标题,以 Revert " 开头,包含了原提交的标题。
  • 中间部分是自动生成的说明,指出了被撤销的提交的哈希值。

通常你不需要修改这个信息,直接保存并关闭编辑器即可。​

  • 在 Vim 中​:按 Esc,然后输入 :wq,再按 Enter
  • 在 VSCode 中​:直接点击保存并关闭标签页。

保存后,Git 就完成了撤销操作,并创建了一个新的提交。

步骤 4:验证结果

再次使用 git log --oneline 查看历史,你会发现多了一个新的提交。

* f6e5d4c (HEAD -> main) Revert "Add feature Z"  <- 新生成的撤销提交
* c3d4e5f Add feature Z                           <- 原来的提交依然在这里!
* b2c3d4e Fix bug in feature Y
* a1b2c3d Implement feature Y
* 9876543 Initial commit

请注意​:原来的提交 c3d4e5f 仍然存在于历史中,新的提交 f6e5d4c 是它的“反操作”。你的工作目录和暂存区的状态现在就像是那个错误的提交从未发生过一样。

步骤 5:推送到远程仓库

由于 revert 是安全的,你现在可以放心地将这个新提交推送到远程仓库(如 GitHub, GitLab)。

git push origin main

现在,你的协作者拉取(pull)代码后,也会得到这个“撤销”的效果,而不会遇到任何历史冲突。


处理特殊情况

1. 撤销合并提交 (Merge Commit)​

撤销一个普通的提交很简单,但撤销一个合并提交需要特别注意,因为它有多个父提交(parent commits)。

当你运行 git revert <merge-commit-hash> 时,Git 会停下来询问你:“你想基于哪个父提交来进行撤销?”

  • ​**-m 1​:表示选择合并提交的第一个父提交**作为主线。这是最常见的情况,通常就是你当前所在的分支(例如 mainmaster)。
  • ​**-m 2​:表示选择合并提交的第二个父提交**作为主线(通常是被合并进来的那个特性分支)。

示例:​
假设你合并了 feature-branchmain,现在想撤销这次合并。

# 查看提交历史,找到合并提交的哈希值
git log --oneline --graph

# 假设合并提交的哈希是 abc1234
git revert -m 1 abc1234

-m 1 的意思是:“撤销这次合并,让 main 分支回到它原本的样子,就好像从来没有合并过 feature-branch 一样。”

2. 一次撤销多个提交

如果你想连续撤销多个提交,可以使用一个范围。

语法:​git revert OLDER_COMMIT^..NEWER_COMMIT

  • OLDER_COMMIT 是你要撤销的最早那个提交的父提交。
  • NEWER_COMMIT 是你要撤销的最新那个提交(即 HEAD 方向)。

示例:​​ 撤销最近的三次提交。

# 假设当前 HEAD 指向提交 D,你想撤销 C, B, A (三个提交)
# ... ---A---B---C---D (HEAD)
# 你需要指定 A 的父提交 (假设是 X)
git revert X^..D

更简单的方法​:使用 git revert --no-commit 逐个撤销,最后手动提交。

git revert --no-commit c3d4e5f # 撤销但不自动提交
git revert --no-commit b2c3d4e # 再撤销前一个
# ... 可以继续撤销更多
git commit -m "Revert multiple commits: c3d4e5f, b2c3d4e"

--no-commit 选项会把所有撤销的更改都放到暂存区,让你有机会一次性提交,形成一个统一的“撤销多个更改”的提交记录,而不是产生多个独立的撤销提交。

3. 撤销操作本身也需要被撤销

如果你 revert 错了,想恢复被撤销的更改怎么办?答案是:​再次 revert 那个 revert 提交

在我们的例子中,如果我们想恢复 “Add feature Z”:

  1. 找到 “Revert ‘Add feature Z'” 这个提交的哈希值(例如 f6e5d4c)。
  2. 再次执行 revertgit revert f6e5d4c 这会创建一个新的提交,其内容是重新应用 c3d4e5f 的更改。

总结与最佳实践

  1. 黄金法则​:​已推送,用 revert;未推送,可用 reset
  2. 检查状态​:在执行 revert 前,最好使用 git status 确保你的工作区是干净的,没有未提交的更改。
  3. 解决冲突​:如果撤销的更改与当前代码有冲突,Git 会提示你解决冲突。解决方法和解决合并冲突一样,然后执行 git add .git revert --continue 来完成操作。如果想放弃本次 revert,可以执行 git revert --abort
  4. 清晰沟通​:由于 revert 会产生新的提交,最好在团队沟通中说明你撤销了哪个提交以及原因,保持透明度。

通过遵循这些步骤,你就可以安全、有效地使用 git revert 来管理你的项目历史,纠正错误而不破坏协作的基石。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞52 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容