【问题标题】:Fixing 'backwards' git merge that was pushed修复被推送的“向后”git合并
【发布时间】:2016-07-12 13:22:52
【问题描述】:

我在我的 git 分支之间遇到了一个问题,我不确定如何解决。假设我正在处理的每个版本都有单独的分支。例如,我有“Release-1”和“Release-2”作为我的分支。这些版本本质上是连续的,即“Release-2”包含“Release-1”中的所有内容,但反之则不然。就我而言,我不小心将“Release-2”合并到“Release-1”中,并在没有意识到我的错误的情况下将其推送。我意识到我犯了一个错误,我继续发布:

git revert -m 1 <sha-of-bad-merge-commit>

这似乎解决了一切; 'Release-2' 代码都没有在'Release-1' 中,并且看起来都是正确的。我把它推到我的上游,认为它已经解决了。快进到今天。我在“Release-1”分支中应用了错误修复。现在,我想将“Release-1”合并到“Release-2”中,但我遇到了冲突。 Git 认为从之前的 revert 中所做的更改应该合并到“Release-2”中。本质上,当我尝试合并时,git 想要从 'Release-2' 中删除意外引入到 'Release-1' 中的更改。

我已尝试研究解决方案,但没有找到。我发现最接近的方法适用于过早合并、还原,然后尝试在以后再次合并。解决方案是还原还原,然后再次进行合并。我不认为这在这种情况下会起作用,因为这会将不应该在“Release-1”中的更改重新引入“Release-1”。

除了逐行查看每个受影响的文件以选择正确的更改集之外,是否有一种好的“基于 git”的方法来解决这个问题?我不想简单地从存在冲突的“Release-2”分支中获取更改,因为其中一些可能是合法的。另外,我考虑过将错误修复分支合并到“Release-2”,但将来可能会再次出现问题。我想防止这种情况发生。

这是一个粗略的情况:

(Release-2) ---A----B----C---x---x---------*D*
                          \               /
(Release-1) ---x----Y------M---x---^M----Z

假设 A、B 和 C 是我想要的“Release-2”的正常提交。 “Release-1”的提示是 Y,只包含“Release-1”的作品。提交'M'是我不小心在'Release-1'分支中合并提交'C'和提交'Y'的地方。在某些时候,我注意到我的错误并恢复合并(提交'^M')。提交'Z'然后有我的修补程序。此时,我想将“Release-1”合并回“Release-2”。我这样做并最终获得'D'。这就是我的问题所在。本质上,我在“D”处的合并告诉它想要删除在“A”、“B”和“C”中所做的所有更改,这是我不想要的。由于合并还原,其他文件显示为冲突。例如,当我进行还原时,我想要在“Release-2”中的一些文件在“Release-1”中被删除。现在,在“D”处,git 告诉我存在合并冲突,因为一个分支删除了文件,而另一个分支修改了文件。

如果有人有任何建议,我将不胜感激。谢谢!

【问题讨论】:

    标签: git version-control merge merge-conflict-resolution


    【解决方案1】:

    (我将您的^M 提交称为Mrevert,因为^ 字符在随后的某些命令中具有特殊含义。)

    执行git merge --abort 以放弃创建提交D 的尝试。

    由于您有一系列提交x--Mrevert--Z,并且您需要拉入xZ 的更改,而不是Mrevert 的更改,因此您需要一个三步流程:

    1. 使用git merge Mrevert^ 拉入直到Mrevert 为止的所有更改。 (c^ 语法的意思是“提交的父级c”。)
    2. 使用git merge -s ours Mrevert 告诉git ^M reversion 提交的更改已经在您的分支中。 -s ours 表示保留我们(即 Release-2 的)版本的树,而不用担心任何真正的“合并”。
    3. 使用git merge Z 合并来自Z 的更改。

    这将生成一个提交图,如下所示:

    (Release-2) ---A----B----C---x---x---M1-----M2------M3
                              \         /      /       /
    (Release-1) ---x----Y------M-------x---Mrevert----Z
    

    如果您执行git diff M1 M2,您会看到M2 不会将任何更改拉入Release-2。

    【讨论】:

    • 这是大部分正确的,如果只有在M^M之间标记为x的提交不存在,这将是完全正确的.我认为做到这一点的方法是进行三个合并而不是两个:一个在提交x中合并,一个与-s ours合并^M,最后一个在提交中合并Z.
    • @Matt 非常感谢!该解决方案按预期工作。我使用 '^' 符号和 'M' revert 的原因是我遵循的插图与此处的插图相同:git-scm.com/blog/2010/03/02/undoing-merges.html
    • @torek 当我按照马特提供的说明进行操作时,我没有注意到“x”提交中有任何问题。我认为这是因为恢复提交根本不会影响“x”,所以它仍然会在以后按预期合并。在“M”中有一些我确实想要在“Release-1.0”中的提交在“^M”中恢复了,所以我不得不做一些额外的工作(提交的樱桃挑选恢复后)以在 Z 处获得这些更改。
    • 您可能不需要或确实通过另一条路径获得该提交的更改。 --ours 合并的基本思想是在提交图中记录合并(以便 next 合并产生正确的合并基础),同时完全忽略合并通常会发生的所有更改添加,其中包括 x 提交中的更改,因此您以后不会从 x 本身获取它们。
    猜你喜欢
    • 2016-07-04
    • 2023-04-06
    • 2016-06-09
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多