Git中的合并冲突是什么?

43

Git如何确定特定合并存在冲突及其冲突内容?

我的猜测是:如果被合并的两个提交具有共同的父提交,并且它们都更改了行X,与父提交不同,那就是一个冲突。

使我困惑的是:

  • “更改行X”可能意味着用几行新代码替换该行,但Git会将其显示为一个冲突(版本A具有此一行,版本B具有这5行或其他内容)。
  • 如果您在其中一个提交中插入了一些行,较简单的算法将认为所有后续行都已更改:第30行现在具有第25行以前的内容,31行具有第26行以前的内容等等。但Git可以告诉这些内容是相同的,我不知道它是如何做到的。

有人能解释这是如何工作的,或者给我一个相关链接吗?

3个回答

23

基本上,使用 git 进行合并时每次都会出现冲突,这会让你拥有一个包含每个文件三个版本的索引:来自每个分支和基础的版本。在这个索引上运行各种解决程序,它们可以为每个单独的文件决定如何解决问题。

第一阶段是一个简单的解决程序,负责处理像未更改的文件、其中一个分支修改了文件而另一个没修改,或者两个分支都包含相同的新文件版本这样的情况。

之后是插件来处理剩余的情况。有一个插件通过识别每个分支中的单个更改(类似于差异),尝试将其应用于另一个分支,如果失败就回退到放置冲突标记。此时你可以轻松地挂接自己的合并工具,例如,你可以编写一个工具,知道如何合并 XML 文件而不违反格式,或者提供图形用户界面,允许交互式编辑和并排查看(例如,kdiff3 就能做到这一点)。

因此,冲突的呈现实际上取决于所使用的插件;文本文件的默认插件将使用与 CVS 相同的样式,因为人们和工具都已习惯,而冲突标记是几乎所有编程语言中都被视为已知的语法错误。


每次合并都会产生冲突?什么意思? - Mark E. Haase
1
@mehaase,这就是它的工作方式。 :) 作为用户,很大一部分内容对您是隐藏的(例如琐碎的解析器),但如果您想要自己的解析器,了解这些内容非常重要。 - Simon Richter
“仅靠插件来查看剩余情况”可能会有些误导,因为无法挂钩调用git merge-file的自定义程序。只有交互式合并工具才能做到这一点(例如kdiff3)。 - DomQ
1
@DomQ,“merge-file”是文本文件的最后一道合并驱动程序。您可以指定使用其他合并驱动程序。 - Simon Richter
1
据我所知,@JanŻankowski,这是提交次数。有多个候选提交,其中一个不是另一个的祖先相对较少见,但在这种情况下可以精确指定要使用哪个基础进行合并。基础版本与其前身之间的差异并不重要。 - Simon Richter
显示剩余4条评论

7

3
浏览此页面上的HOW CONFLICTS ARE PRESENTED段落。
注:冲突情况和文件冲突标记没有真正的文档,因为我在这里被评论猛烈抨击,所以这里是指向源代码的指针,可以接近Git遵循什么策略来实现冲突状态。文件merge-recursive.c,搜索"CONFLICT"字符串。通过这样做,我们可以很容易地发现有一些冲突情况,如:
  • CONFLICT(重命名/重命名)
  • CONFLICT(内容)
  • CONFLICT(重命名/目录)
  • CONFLICT(重命名/删除)
  • CONFLICT(重命名/添加)
  • CONFLICT(删除/修改)
  • ...等等
如果你问我,是的,它们应该被记录并清楚地指出,但它们没有被记录下来,所以除了检查源代码之外别无选择...但是有人真的可以从这里开始并创建一个好的文档,然后将其发送给Git项目。
@Wim Coenen是的,它也取决于合并策略,但展示冲突的方式更能提供深入的见解。如果你问我,那么你也可以阅读合并策略,但你仍然会有疑虑。

你倒不如说“去读文档吧”。就我个人而言,我觉得 git 的文档在这方面有点晦涩。 - Blair Holloway
我没有给这个链接点踩是因为它很有趣,但它并不完全符合我的要求。那段话展示了在 git 决定存在冲突之后的情况。我想学习的是 git 如何首先判断是否存在冲突。 - Nathan Long
相关段落实际上是合并策略。 - Wim Coenen
1
@Wim Coenen - 那段话暗示着我的问题的答案取决于您选择的合并策略。这很有趣,但就像“嘿,你以为你不理解一件事,现在有十件事你不理解!” :) 也许我们可以针对这个问题使用默认策略来解决? - Nathan Long

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