修复一个已提交但未解决的合并冲突。

4

代码库中有一些文件包含与HEAD和另一个提交的合并冲突语法。这些文件不知何故已经提交,我现在无法查看日志。我搜索到了使用“git merge -X theirs”命令合并文件的方法,但是会出现“文件没有指向提交”的错误。

如何自动从 <<<<<

3个回答

4
如果你已经合并并提交了,再次合并将不会产生任何有用的结果。就git而言,你对合并感到满意。(虽然你刚才说你不满意,但是你不能告诉git. :-) )
如果错误的合并没有与其他人共享,最简单和可能也是最好的解决方法是“撤销”它,然后重新进行更正的合并。(如果在此之后还有其他提交,则可以挑选这些提交并将其添加到更正的分支中。)
如果错误的合并被其他人共享,你仍然可以执行重置/重新合并/挑选序列,但所有共享此内容的“其他人”都需要知道如何从中恢复。或者,你可以保留错误的合并,但通过其他方式进行修复。对于这种情况,没有一个单一的最佳答案。
要“撤销”合并,你需要了解git如何首先执行合并以及分支标签如何与提交图形配合工作。让我们画一个示例图形片段:
... - C - D - E ----- M - I  <-- main
        \           /
          F - G - H          <-- feature

在这里,你曾经有一个指向提交Cmain分支名称。然后你(或其他人)创建了feature分支。接着你(或其他人)回到main分支并进行了两次提交DE,同时你(或其他人)在feature分支上工作并进行了三次提交FGH
(每个字母代表一个40个字符的SHA-1 ID,例如d1574b852963482d4b482992ad6343691082412f。)
最终,你(或其他人)进入main分支并运行git merge feature。这个合并有很多冲突,但是你(或其他人)只是添加和提交了Git留下的文件混乱,而没有正确地解决合并。这就是导致合并提交M的原因。 如果你还没有提交,那么提交M不存在(因此也不存在提交I)。你只需要运行git merge --abort来停止正在进行的合并。这将使你回到这个图形,你在main分支上(我假设是这样,但你也可能在feature分支上,在这种情况下,一旦你做出M,它将在下面的feature分支上,而不是在上面的main分支上)。
... - C - D - E        <-- main
        \
          F - G - H    <-- feature

这是你现在所期望的图像,如果你打算“撤销”合并操作,即使提交 M 已经存在。

即使提交 M 存在,也很容易实现。这是因为这些分支尖端指针——存储在分支名称中的东西——仅仅指向某个提交。 我假设现在 main 指向提交 I。 我们可以将提交 M 和提交 I 保留在图形中,只需让 main 再次指向提交 E

... - C - D - E              <-- main
       \       \
        \       `--- M - I   <-- ???
         \          /
          F - G - H          <-- feature

首先,我们需要确保保存提交 I 的身份,通过创建一些标签(分支或标签名)指向它。也就是说,让我们填写三个问号。我们可以使用 git tag 创建一个标签来实现这一点:

git tag save-main main

或者使用 git branch 创建一个分支。两种方法都可以正常工作。

现在我们只需要让 main 指向 E,就像图中所示。最简单的方法是使用剪切和粘贴或者通过计数回退来实现。在这种情况下,计数回退显示两次跳跃会到达 E(一次跳跃会到达 M),因此:

git reset --hard HEAD~2

这将把当前分支(即main)在图形中向后移动两步(到E),并重新设置工作树以匹配给定的提交(再次是提交E:我们只是使用名称HEAD~2进行命名)。如果您喜欢,可以使用原始SHA-1,可以通过git log找到。


请记住,上面的所有内容都只是为了使我们回到尚未尝试将git merge feature合并到main的情况下。现在我们已经完成了这个任务;我们的图表看起来像我们想要的那样。

现在我们可以按照我们想要的方式进行合并:

git merge -X theirs feature

这一次,我们应该仔细检查结果,确保我们工作树中的文件看起来符合我们的期望。否则,我们将再次产生混乱的合并提交,并回到原点。但是让我们假设一切顺利。 git merge将成功并实际进行合并提交。曾经有一个提交M,这是一个不同的提交,M仍然存在——我们的save-main标签指向I,而I指回M——所以我们现在的图形具有新的合并M2

... - C - D - E ----  M2      <-- main
       \       \    /
        \       `--/- M - I   <-- save-main
         \        | /
          F - G - H           <-- feature

作为最后步骤,我们可能想通过将 I 复制到一个新的提交 I' 中来恢复内容。为了做到这一点,我们可以简单地使用 git cherry-pick 命令:

git cherry-pick save-main

名称save-main指向提交I,因此这将复制我们在I中所做的任何操作,并将其添加到我们当前的分支main中:
... - C - D - E ----  M2 - I' <-- main
       \       \    /
        \       `--/- M - I   <-- save-main
         \        | /
          F - G - H           <-- feature

现在我们已经完成了名称为save-main的部分,因此我们可以删除它:

git tag -d save-main

由于我们不再关心提交MI,因此可以“撤消”合并提交M,方法是将分支名称main“倒回去”。

(请注意,挑选提交I可能会出错,因为I是建立在错误的合并M之上的。如果失败了,尝试执行挑拣操作时会出现合并冲突。您需要手动解决这个问题。)


请注意,上述描述的过程,“撤消”合并提交M,通过“倒回”分支名称main,会给那些正在共享您的工作的人(直接使用您的存储库,或者如果您已经git push了有问题的合并,以便其他人可以看到,或其他情况)带来麻烦。他们也必须撤消有问题的提交,如果他们已经基于这些有问题的提交进行了自己的工作,则可能必须重复其工作。在这种情况下,您可能需要采取不同的方法,通过添加新的提交来修复失败的合并(例如,手动清理混乱)。在这种情况下,共享您的工作的人将简单地将您的修复选为修复,这是git的设计目标,因此对他们来说更容易。


0
根据git-merge文档theirs是一个有效的命令,但在这种情况下,您可能还需要明确指定递归策略:
git merge -s recursive -X theirs

0
尝试回滚您的冲突,如果合并不起作用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接