【问题标题】:Why do merge conflicts happen?为什么会发生合并冲突?
【发布时间】:2016-04-07 03:46:44
【问题描述】:

例如:

  • 我有一个 master 分支。
  • 我创建了一个文件file.txt,并在其中写入Master branch,然后提交。
  • 我创建另一个名为fix20的分支,并将file.txt的文本修改为This is fix20 branch。然后我提交它。
  • 我切换到 master 分支,然后创建一个分支 hotfix 并切换到它。
  • 我将file.txt 修改为文本This is the HotFix。之后我提交更改。
  • 现在我切换回主分支并将其与修补程序合并。该文件(没有问题)将其文本更改为This is the HotFix(它们基本上已合并)。

现在我与 fix20 分支合并,我遇到了合并冲突。 file.txt 既有来自 fix20 分支的文本,也有我与 HotFix 合并后的文本。此时,我应该打开一个编辑器并决定,应该留下什么,应该删除什么。

问题是:为什么会发生第二次合并冲突?当我将主文件与修补程序合并时,为什么我没有决定留下哪些文本?当我与 fix20 分支合并时,为什么没有合并文件(为什么文本不像修补程序那样被替换)?为什么基本上这种冲突发生第二次而不是第一次???

【问题讨论】:

  • branch fix20 的提交历史与 master 分支不同,master 没有,git(或任何其他版本工具)无法知道您是要保留两个文本还是只保留其中一个跨度>
  • @NikosM。那为什么当我将它与修补程序合并时,我想保留什么的问题没有出现??
  • 因为master改变了某个commit,而fix20也有另外一个,所以工具无法知道
  • @NikosM。是否像这种情况,需要重新定位?
  • 不一定,除非你想重新设置分支,例如你可能只需要添加到分支,而不是重新设置

标签: git github version-control merge


【解决方案1】:

阅读this answer 了解完整详情。它与您遇到的问题相同,但情况略有不同


简而言之:

答案是存在冲突,因为这两个分支没有任何merge-base 提交。


这是您描述的步骤


我使用 3-diff ads diff 算法

这是文件的内容:

<<<<<<< HEAD
This is hotfix branch
||||||| merged common ancestors
Master branch
=======
This is fix20 branch
>>>>>>> fix20

我已尝试生成一些关于您的问题的图形表示,但它花费了太多时间。

我会尽量在这里回答清楚。

因为你有几个分支,每当你做一个合并 git 尝试找出分割完成的地方(你在哪个提交上派生并打开了新分支)。然后从这一点开始生成差异并尝试合并文件。

我们的情况是这样的:

master            master  master
   \----- hotfix --- /     |
   |                       |
   \----- fix20  ----------/


// To view the patch that will be created for the merge you can run
// this command and you will see the commits that will be merged.
git log ^master fix20 

在您的情况下,您会看到它试图合并更新相同文件的提交(两个分支都是从同一个提交 [merge-base commit] 创建的)并导致冲突。

【讨论】:

  • merge-base 是什么意思?附言我明白了,这篇文章和我的一样,但我还是不明白,为什么会这样
  • 写下原因,我会花几分钟时间
  • 请您至少解释一下合并基础是什么意思?问题基本上是:“为什么会发生这种情况”,而您刚刚写到它发生了。
  • 等等,还在为你写完整的答案。还有几分钟
  • 使用merge base的通用定义,这里肯定有一个,即commit c4d6cfb(root commit)。
【解决方案2】:

这里的问题是你知道你的意图......但 Git 不知道。

这就是 Git 如何看待您所做的事情:您对同一行进行了两次独立的更改。当您合并第一个时,您的意图很明确:您希望更改成为 master 的一部分。由于自您分支以来 master 本身没有任何更改,因此没有任何问题:Git 总是可以直接合并一段代码如果只有合并的一侧更改了它

当您尝试合并第二个更改时,情况不再如此:通过合并第一个分支,您向 master 引入了与第二个分支中的更改不直接“兼容”的更改。 Git 称之为:“分支已经分道扬镳”。 Git 不知道您是希望保留从第一个分支合并的内容,还是保留从第二个分支合并的内容。

在您的情况下,对您来说很明显,因为第二个分支是对同一事物的较新修复...但是许多合并涉及对代码进行更复杂的更改,并且可能是正确的合并方式第二个分支是合并来自两个合并的更改:通常,如果两个合并的更改涉及同一行代码,则两者都必须在上面留下自己的标记。

示例原代码:

send_request("bake cookies")

分支 1:

send_request("bake cookies", additions: ["chocolate"])

分支 2:

send_request("bake cookies", flour: "wheat")

合并这两行的正确方法可能不是逐字逐句取两行之一,它可能更像这样:

send_request("bake cookies", flour: "wheat", additions: ["chocolate"])

由于您比 Git 更了解代码的意图,因此 Git 永远不会在这种情况下自动做出决定。

【讨论】:

  • 我会补充说 git 就像任何版本工具一样适用于差异(序列),差异描述了什么改变了。在 master 的情况下,差异很清楚,一行更改为另一行,但在分支的情况下,差异不能按原样应用(注意,所有版本工具都会发生同样的情况,因为它们使用diff 模式,不仅是 git)。工具中的每个版本历史只是一系列差异(按顺序应用),git在其他方面与其他工具不同,但不是这个
猜你喜欢
  • 1970-01-01
  • 2014-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-09
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多