修复在 Git 中完成合并的方式
Posted
技术标签:
【中文标题】修复在 Git 中完成合并的方式【英文标题】:Fix the way a merge was done in Git 【发布时间】:2016-01-05 15:39:55 【问题描述】:这是我面临的情况:一个开发分支被合并到 master 中。分支做的工作很棒,但是冲突的解决很糟糕(使用了--ours)
-x--x--x--M--z--z
/
-a--a--a
x 和 a 中的内容很好,但问题来自 M。所以,理想情况下,我想还原合并 M 并再次合并,但这只能通过“还原还原”来完成,这不允许我改变合并的方式(如果我没记错的话)。
我该怎么做?
(所有的提交已经被推送和共享,所以我想避免重置)
【问题讨论】:
develop 分支是否仍然存在并且处于合并之前的状态? (即没有新的提交) 是的,它还在那里,没有动过 【参考方案1】:至少有两种选择:
A.修复原来的合并
如果您想撤消合并并以不同的方式再次执行,您将转到 rewrite history,这意味着 M
的 SHA-1 哈希值和所有以下提交都将进行改变。如果您无法与克隆存储库并可能已经获取旧提交的每个人进行沟通,这可能是一个问题。
话虽如此,您可以通过 interactive rebase 修复合并提交。
假设HEAD
在master
:
x--x--x--M--z--z <- master, HEAD
/
a--a--a
你可以的
git rebase -i HEAD~3 --preserve-merges
从 HEAD 之前的 3 次提交开始 rebase,这将是合并提交之前的提交。 --preserve-merges
选项确保合并提交本身可用于在 TODO 列表 中进行修改。此时您可以将M
标记为edit
并继续修改它。
B.进行新的提交
如果您不想重写历史记录,最简单的解决方案是简单地进行新的提交,以纠正由原始合并 M
引入的任何错误:
x--x--x--M--z--z--F <- master, HEAD
/
a--a--a
其中F
是一个新提交,它通过修复它引入的问题来补偿M
。
【讨论】:
感谢您的回答!我终于以另一种方式做到了,对此答案有何看法? 再次阅读您的回答后,我有一个疑问。 rebase 解决方案真的会重写历史吗? 您的方法确实有效,但我认为它过于复杂化了历史。如果您打算通过新的合并补偿M
引入的错误,您不妨在master
的顶部进行新的补偿提交。请参阅我的更新答案。
是的,通过 rebase 修复原始合并,从合并提交开始重写历史记录。
感谢您的反馈!实际上,结果与最终的新补偿提交相同。不同之处在于我可以在冲突中看到哪些文件受到错误合并策略的影响,而不必检查整个提交并搜索它们。【参考方案2】:
我想我终于自己想通了。
我的想法是在有问题的合并之前从 master 创建一个新分支,重新创建(正确)与 development 分支的合并,从 master 中挑选提交,最后合并回 master。
更详细地说,我在有问题的合并之前创建了一个分支“修复”,并将开发分支合并到新分支中。然后我可以根据需要合并两个分支。
-x--x--x--M--z--z
X
-a--a--a \
\ \
M'
然后,我从主人那里挑选提交
-x--x--x--M--z--z
X
-a--a--a \
\ \
M'--z--z
最后,我合并了 master 上的 'Fix' 分支。这将产生另一组需要修复的冲突(由于两次合并)(但几乎可以肯定的是,可以保留来自“修复”分支的更改)。最终,主人处于我想要的状态。
-x--x--x--M--z--z-----N
X /
-a--a--a \ /
\ \ /
M'--z--z
至少,这对我来说是有效的。
【讨论】:
如果你在提交时先将M
合并到M'
但文件树的状态与M'
相同,使用类似merge -n ...; reset M' -- .; commit
序列然后将该提交合并到当前分支的最新状态。这是您没有解决可能在M
和M'
之间的冲突(您希望以M'
解决)并且可能在M'
和您可能想要的分支的最新状态之间解决“相当”。
@CharlesBailey 你是对的,这可能会更短更容易!以上是关于修复在 Git 中完成合并的方式的主要内容,如果未能解决你的问题,请参考以下文章