Git 对已标记为合并的文件进行三向合并

Git three-way merge on files already marked merged

为了保留从master分支合并到develop分支的冲突解决历史,我按原样进行状态提交,然后再提交冲突解决。

在第一次提交时,我没有采取任何措施来解决冲突,因此保留了所有“<<<<<<<<=========>>>>>>>>”在源代码中。在第二次提交中,我明确地解决了冲突。

问题是,我在第一次提交时将文件标记为已解决后,我不知道如何在第二步进行三向合并。那么我应该如何git对已经标记为合并的文件进行三向合并呢?

按照您的方式做事几乎没有价值,所以我建议您只完成合并并提交。不过, 是一种可以为所欲为的方法。问题是您需要找到正确的三个输入文件。在 git merge 冲突期间计算并提供了正确的输入文件集,但不再可用 - 您必须重新计算它们。

三个输入文件是:

  • 合并基础版本;
  • 左侧或--oursHEAD或"local"版本;和
  • 右侧或 --theirs 或 "remote" 版本。

当您编辑工作树文件并看到:

auto-merged result text
<<<<<<< HEAD
some text
=======
different text
>>>>>>> their-branch
more auto-merged text

您看到的文字是 Git 结合这三个输入的最大努力。当时索引中的实际输入,分别为"stage 1"、"stage 2"和"stage 3"。如果你 运行 git mergetool,例如,为了完成合并,git mergetool 命令使用 git checkout-index 来提取这三个文件(它称为 BASE、LOCAL 和 REMOTE) .

当您提交合并时,Git 删除了三个输入。它们不再可用。您通常可以 再次找到它们。这是他们的来源:

  • 合并基础文件是从合并基础提交中提取的。

    要查找合并基础提交哈希 ID,请使用 git merge-base --all。您还需要其他两个提交哈希 ID。如果生成的合并基础 ID 是 bbbbbbb,那么您可以 运行:

    git 显示 bbbbbbb:path/to/file > file.base

    在当前工作树中重建文件的合并基础副本。

  • 左侧文件可能来自您当时使用的提交。 (当您使用修改后的工作树文件作为左侧文件时,会出现此规则的例外情况。在这种情况下,左侧版本 not 可通过 Git。)所以你需要这个散列 ID。假设它是 1111111;然后:

    git show 1111111:path/to/file > file.local
    

    将在当前工作树中重新创建该输入。

  • 最后,右侧的文件来自您正在合并的提交。您将需要最后一次提交的哈希 ID。假设它是 2222222;然后:

    git show 2222222:path/to/file > file.remote
    

    将在当前工作树中重新创建该输入。

所有这些都假设在合并过程中没有检测到文件重命名。如果有这样的重命名,请为三个输入提交中的每一个选择正确的路径名。

获得所有三个输入后,您可以使用 the git merge-file command 将它们组合起来,方法与 git merge 相同。这将在这三个文件之一中留下带有冲突标记的合并结果。有关详细信息,请参阅链接文档。

最后,请注意,您可以 重新-运行 合并,方法是将 then-HEAD 提交签出为 分离 HEAD。您可以通过检查合并提交来找到 then-HEAD 和其他提交哈希 ID:它有两个父项,这两个父项分别是左侧和右侧提交。因此,如果合并提交具有哈希 ID $M,则:

git checkout $M^1     # detach HEAD at left side commit
git merge $M^2        # re-execute the merge with right hand side commit

将重复 git merge 第一次所做的工作,计算相同的合并基础并执行相同的合并工作并产生相同的合并冲突。有关 <revision>^1<revision>^2 表示法的更多信息,请参阅 the gitrevisions documentation。当冲突再次发生时,更高阶段的条目将再次出现在您的索引中。