在软件开发中,犯错在所难免,但如何处理错误尤其是在团队协作中至关重要。
当您在共享代码仓库中使用 Git 时,您不仅要撤销一次不良提交,更要以安全的方式进行。这也是我结合自身经验撰写这篇关于 git revert 的原因。
与 git reset 会抹去历史不同,git revert 会创建一个新的提交,用来撤销先前提交引入的更改。这种做法能保留提交历史。
如果您对这些概念还不熟悉,可以学习我们的 Git Fundamentals 技能路径,全面了解代码仓库与版本控制。
什么是 Git Revert?它如何工作?
可以把 git revert 理解为 Git 在说:“我们安全地撤销它吧。”当某次提交混入了问题——可能是一个 bug、拼写错误,或是仓促的修改——您或许会想直接删掉它。但在共享仓库中,删除历史可能带来比原始错误更大的麻烦。这就是 git revert 存在的意义。它不抹去提交,而是新增一个提交来抵消那次更改。
那么,git revert 到底做了什么?
-
它会新增一个提交:正如我之前所说,git revert 不会清除任何东西,而是创建一个新的提交来撤销您要回退的那次提交中的具体更改,从而保持项目历史一致。
-
它会立即应用更改:如我尚未提到的,一旦您运行 git revert 命令,被撤销的更改会立刻出现在工作区中。您能马上看到修复效果。
-
它不会影响暂存区(除非产生冲突):还有一点需要了解:Git 会在内部处理 revert。如果一切顺利,无需手动暂存文件。不过,如果 Git 无法确定如何逆转某些更改(例如复杂合并的情况),它会请求您介入协助。
撤销提交之后会发生什么
当您运行了 git revert,到底发生了什么?Git 并不会删除任何内容,而是创建一个新提交,来逆转目标提交所做的更改。这个新提交会被添加到已有历史的顶部,这意味着原始提交保持不变且完全可见。历史不会被重写或移除;Git 只是加了一层“撤销该更改”的记录。同时,这次逆转带来的文件修改会立即应用到您的工作区。您会立刻看到修复生效,就像其他提交一样。
这一过程使 git revert 成为对已推送到共享分支的错误进行修复的最安全方式。团队中的每个人都能清楚看到哪些内容被修改、哪些被撤销,以及原因何在,不会干扰正在进行的工作。
git revert 与 git reset 对比
虽然 git revert 与 git reset 都能用来撤销提交,但它们的工作方式本质不同。git reset 适合本地、私有的修复,可用于清理凌乱的提交并按您的意愿重置工作区。但它有个风险:如果您已经推送了工作内容,然后又使用 git reset,通过更改共享的提交历史,可能会给队友带来麻烦。
相反,git revert 专为共享或公共分支设计。它不会删除任何东西,而是创建一个新提交来抵消较早提交引入的更改,因此在共享项目中更安全。
下面的并排对比可以帮助您更清楚:
|
特性
|
git revert
|
git reset
|
|
动作
|
新增一个提交以逆转先前的提交
|
移动分支指针,并可选择修改文件
|
|
提交历史
|
保留,不删除任何内容
|
被重写的提交可能丢失
|
|
最佳用途
|
在公共/共享分支上撤销更改
|
在推送前清理本地提交
|
|
对他人的影响
|
安全,不会干扰协作者
|
有风险,如共享历史会导致冲突
|
|
工作区
|
更改会立即应用
|
可能重置文件状态(--soft、--mixed、--hard)
|
|
理想场景
|
回退已推送的不良提交
|
在本地功能分支中重写提交历史
|
回退多个提交
有时问题不止一个提交,您可能需要撤销一整串提交。幸运的是,Git 允许您使用一次命令并通过提交范围来回退多个提交。
语法如下:
git revert OLDEST_HASH^..NEWEST_HASH技术支持
这会告诉 Git 从最旧提交之前(这就是 ^ 的含义)开始,依次回退直到并包含最新的那个提交。例如:
git revert a1b2c3d^..d4e5f6g技术支持
该命令会为该范围内的每一个原始提交生成单独的回退提交。
注意,一次性回退多个提交往往会触发合并冲突,尤其当这些提交修改了同一文件或同一行时。Git 会尝试按顺序逆转每个提交,但可能需要您协助解决重叠的更改。
您也可以进一步了解 Git 如何处理回退操作(包括更棘手的情况,如合并提交)请参阅 Git Revert Merge Commit: A Guide With Examples。
在回退过程中处理合并冲突
回退听起来很简单,直到 Git 给您“出难题”——合并冲突。通常在以下情况下出现:
- 您要回退的提交与其他近期提交修改了相同的代码行。
- 您正在回退一个合并提交,或一组存在重叠变更的提交。
Git 会尽力干净地逆转更改,但一旦存在歧义,它会暂停并请求您的帮助。
处理方法如下:
git revert HEAD技术支持
另外,要查看哪些文件存在冲突,请使用:
git status技术支持
在代码编辑器中手动解决冲突,查找 <<<<<<<、======= 和 >>>>>>> 标记。
接下来,我将其标记为已解决:
git add <resolved-file>技术支持
然后继续回退:
git revert-- continue技术支持
如果您改变主意,想要彻底取消这次回退:
git revert --abort技术支持
这种流程让您完全掌控。您可以决定是继续回退还是彻底退出。
如果您想了解 Git 如何在此类操作中跟踪引用日志,请查看 Git Reflog: Understanding and Using Reference Logs,获取处理历史混乱的实用技巧。
特殊情况:回退合并提交
回退普通提交相对简单,但合并提交通常更棘手。因为合并提交有两个或更多父提交,Git 需要知道应将哪条路径(即“主线”)视为基线。
要回退合并提交,您需要显式使用 -m 标志。
git revert -m 1 <merge-commit-hash>技术支持
以下是 -m 标志的作用:
何时使用 1 或 2?
使用 git revert 的最佳实践
想要更好地使用 git revert 并避免常见错误,请牢记以下最佳实践:
- 当出现意外时使用 reflog 进行恢复:在回退过程中犯了错?使用 git reflog 查看最近的操作并恢复丢失的状态。
结语
在专业协作环境中,使用 git revert HEAD 将 git revert 到上一次提交,既能保持透明度,又能降低意外数据丢失的风险。无论是在清理失误还是回滚缺陷,revert 都能让您的仓库对所有参与者来说保持稳定且易于理解。
在软件开发中,犯错在所难免,但如何处理错误尤其是在团队协作中至关重要。
当您在共享代码仓库中使用 Git 时,您不仅要撤销一次不良提交,更要以安全的方式进行。这也是我结合自身经验撰写这篇关于
git revert的原因。与
git reset会抹去历史不同,git revert会创建一个新的提交,用来撤销先前提交引入的更改。这种做法能保留提交历史。如果您对这些概念还不熟悉,可以学习我们的 Git Fundamentals 技能路径,全面了解代码仓库与版本控制。
什么是 Git Revert?它如何工作?
可以把
git revert理解为 Git 在说:“我们安全地撤销它吧。”当某次提交混入了问题——可能是一个 bug、拼写错误,或是仓促的修改——您或许会想直接删掉它。但在共享仓库中,删除历史可能带来比原始错误更大的麻烦。这就是git revert存在的意义。它不抹去提交,而是新增一个提交来抵消那次更改。那么,
git revert到底做了什么?它会新增一个提交:正如我之前所说,
git revert不会清除任何东西,而是创建一个新的提交来撤销您要回退的那次提交中的具体更改,从而保持项目历史一致。它会立即应用更改:如我尚未提到的,一旦您运行
git revert命令,被撤销的更改会立刻出现在工作区中。您能马上看到修复效果。它不会影响暂存区(除非产生冲突):还有一点需要了解:Git 会在内部处理 revert。如果一切顺利,无需手动暂存文件。不过,如果 Git 无法确定如何逆转某些更改(例如复杂合并的情况),它会请求您介入协助。
撤销提交之后会发生什么
当您运行了
git revert,到底发生了什么?Git 并不会删除任何内容,而是创建一个新提交,来逆转目标提交所做的更改。这个新提交会被添加到已有历史的顶部,这意味着原始提交保持不变且完全可见。历史不会被重写或移除;Git 只是加了一层“撤销该更改”的记录。同时,这次逆转带来的文件修改会立即应用到您的工作区。您会立刻看到修复生效,就像其他提交一样。这一过程使
git revert成为对已推送到共享分支的错误进行修复的最安全方式。团队中的每个人都能清楚看到哪些内容被修改、哪些被撤销,以及原因何在,不会干扰正在进行的工作。git revert 与 git reset 对比
虽然
git revert与git reset都能用来撤销提交,但它们的工作方式本质不同。git reset适合本地、私有的修复,可用于清理凌乱的提交并按您的意愿重置工作区。但它有个风险:如果您已经推送了工作内容,然后又使用git reset,通过更改共享的提交历史,可能会给队友带来麻烦。相反,
git revert专为共享或公共分支设计。它不会删除任何东西,而是创建一个新提交来抵消较早提交引入的更改,因此在共享项目中更安全。下面的并排对比可以帮助您更清楚:
特性
git revert
git reset
动作
新增一个提交以逆转先前的提交
移动分支指针,并可选择修改文件
提交历史
保留,不删除任何内容
被重写的提交可能丢失
最佳用途
在公共/共享分支上撤销更改
在推送前清理本地提交
对他人的影响
安全,不会干扰协作者
有风险,如共享历史会导致冲突
工作区
更改会立即应用
可能重置文件状态(--soft、--mixed、--hard)
理想场景
回退已推送的不良提交
在本地功能分支中重写提交历史
回退多个提交
有时问题不止一个提交,您可能需要撤销一整串提交。幸运的是,Git 允许您使用一次命令并通过提交范围来回退多个提交。
语法如下:
这会告诉 Git 从最旧提交之前(这就是
^的含义)开始,依次回退直到并包含最新的那个提交。例如:该命令会为该范围内的每一个原始提交生成单独的回退提交。
注意,一次性回退多个提交往往会触发合并冲突,尤其当这些提交修改了同一文件或同一行时。Git 会尝试按顺序逆转每个提交,但可能需要您协助解决重叠的更改。
您也可以进一步了解 Git 如何处理回退操作(包括更棘手的情况,如合并提交)请参阅 Git Revert Merge Commit: A Guide With Examples。
在回退过程中处理合并冲突
回退听起来很简单,直到 Git 给您“出难题”——合并冲突。通常在以下情况下出现:
Git 会尽力干净地逆转更改,但一旦存在歧义,它会暂停并请求您的帮助。
处理方法如下:
另外,要查看哪些文件存在冲突,请使用:
在代码编辑器中手动解决冲突,查找
<<<<<<<、=======和>>>>>>>标记。接下来,我将其标记为已解决:
然后继续回退:
如果您改变主意,想要彻底取消这次回退:
这种流程让您完全掌控。您可以决定是继续回退还是彻底退出。
如果您想了解 Git 如何在此类操作中跟踪引用日志,请查看 Git Reflog: Understanding and Using Reference Logs,获取处理历史混乱的实用技巧。
特殊情况:回退合并提交
回退普通提交相对简单,但合并提交通常更棘手。因为合并提交有两个或更多父提交,Git 需要知道应将哪条路径(即“主线”)视为基线。
要回退合并提交,您需要显式使用
-m标志。以下是
-m标志的作用:-m代表 mainline,告诉 Git 保留哪一个父提交。1通常指第一个父提交,即执行合并时您所在的分支。2指第二个父提交,通常是被合并进来的分支。何时使用 1 或 2?
如果您想撤销合入变更的影响,但保留主分支上的工作,请使用
-m 1。如果您想移除主线的更改,但保留功能分支(或被合并分支)的内容,请使用
-m 2。这种情况较为少见。回退合并提交容易引发冲突,并常常导致复杂局面,尤其当后续提交依赖于它时。如果拿不准,先在测试分支尝试回退。使用 git revert 的最佳实践
想要更好地使用
git revert并避免常见错误,请牢记以下最佳实践:在回退前核对提交哈希:始终使用
git log或git log-- oneline检查提交历史,确保瞄准正确的更改。您可以在 Foundations of Git 课程中巩固这些命令,或借助我们的 Git Cheat Sheet 随时查阅要点。自定义提交信息:不要只用 Git 的默认“Revert”信息。添加上下文——例如为何要回退此提交——以便协作者(以及未来的您)理解这次变更。
在共享分支回退时及时沟通:如果您在公共分支(如 main 或 develop)上回退更改,请先通知团队。回退会影响所有人,最好协调进行。进一步了解协作工作流,请参阅我们的 GitHub Concepts 和 Intermediate GitHub Concepts 课程。
避免“回退的回退”,除非您非常确定:回退此前的回退,可能带回非预期更改或引发冲突。如果需要重新应用某项更改,考虑使用 git cherry-pick 替代。
结语
在专业协作环境中,使用
git revert HEAD将git revert到上一次提交,既能保持透明度,又能降低意外数据丢失的风险。无论是在清理失误还是回滚缺陷,revert 都能让您的仓库对所有参与者来说保持稳定且易于理解。