将功能分支合并到主发布分支 (main) 后,您可能会发现一个严重的错误,需要您立即回滚集成。
通过标准提交,您可以使用 git revert <commit-hash> 轻松撤消更改。但是,尝试恢复合并提交会直接导致 Git 错误:fatal: commit <hash> is a merge but no -m option was given.
在本指南中,我们将解释为什么合并恢复需要特殊处理,逐步使用 git revert -m 选项,并揭示稍后重新合并恢复功能的隐藏陷阱。
1. 为什么 Git 需要 -m 选项?
典型的提交只有一个父提交(其直接前任)。恢复它很简单,因为 Git 确切地知道要减去什么。
相反,合并提交有两个或多个父提交(表示正在合并的分支和正在合并的分支)。 Git 不知道哪个父级应该被视为“主线”历史记录。如果没有指示,Git 无法确定应保留哪些分支的更改以及应丢弃哪些分支。
-m(或 --mainline)选项告诉 Git 要保留哪个父路径。
2. 逐步合并还原
第 1 步:检查合并提交父项
首先,检查目标合并提交:
git show <merge-commit-hash>
在输出的顶部,找到 Merge: 行:
commit a1b2c3d4e5f6...
Merge: 9e8d7c6 5a4c3d2
这些哈希值代表父提交:
- 父级 1 (
9e8d7c6):接收合并的分支(例如main)。 - 父级 2 (
5a4c3d2):合并的分支(例如feature)。
步骤 2:执行指定父级 1 的恢复
要保留 main 分支(父分支 1)的历史记录并回滚传入的更改,请运行:
git revert -m 1 a1b2c3d4e5f6
Git 将打开编辑器来完成提交消息。保存以执行还原。
3. 重组陷阱
当您在修复错误后尝试将相同的功能分支合并回 main 时,会发生恢复合并提交的最棘手的方面。
如果您尝试简单的合并,Git 将仅导入新的错误修复。您的大部分原始功能代码将丢失。
为什么会出现这种情况?
Git 会跟踪原始功能分支提交已合并到 main 中的事实。您运行的 revert 操作没有删除这些提交;它只是添加了一个新的提交来撤消他们的修改。因此,Git 假定功能提交已经存在,并在第二次合并期间忽略它们。
解决方案(恢复恢复):
要成功重新应用功能分支,请勿合并分支本身。相反,恢复原始的恢复提交。
# Reverts the revert commit, re-enabling the original changes
git revert <revert-commit-hash>
这会带回所有原始功能更改,允许您合并后续的错误修复而不会丢失代码。
结论
恢复合并是一项关键的恢复技能。记住:
- 指定
-m 1来指定目标主线分支。 - 了解恢复是添加更改的新提交,而不是删除历史记录。
- 通过恢复恢复提交而不是重新合并来恢复恢复的功能。
了解这些机制可确保您可以自信地管理版本回滚。

