为什么改变相邻的代码行但分别修改会导致Git合并冲突?

8

假设我在主分支(master)上有一个提交(commit),文件名为test.txt,文件中只有一行代码Hello world!并以换行符结尾(这样可以防止在添加第二行时第一行出现差异)。

接着,我从这个提交(commit)创建了一个名为modification的分支(branch)。在这个分支(branch)上,我对文件进行了修改:

Hello world!

为了

Hello world!
This is another line.

然后我提交到该分支。

然后我检出主分支并更改文件从

Hello world!

为了

Hello world! This is a new thing.

然后我提交到master上。总结来说,在这两个提交中,我只改变了一行。由于我在master开头有一个换行符,在master上的额外提交修改第1行,而在modification上的提交修改第2行。因此,当我尝试将modification合并到主分支master时,我不明白为什么会出现合并冲突。然而,我得到了diff3输出结果。

<<<<<<< HEAD
Hello world! This is a new thing.
||||||| merged common ancestors
Hello world!
=======
Hello world!
This is another line.
>>>>>>> modification

为什么 Git 无法意识到修改的是不同的行,并将这两个修改合并在一起?我认为它应该将来自 master 分支的第一行修改和来自 modification 分支的第二行修改合并起来形成以下结果:
Hello world! This is a new thing.
This is another line.

我能想到的唯一可能性是,无论行号如何修改同一个代码块。有趣的是,如果我在第三行而不是第二行添加“这是另一行”,并保持分支上的空行,则合并将继续进行而不会产生冲突。
1个回答

9
你的想法是正确的:如果两个“方面”触及了“同一文件”的“相同行”,与合并基础提交中该文件的内容相比,Git会声明冲突。关键在于定义“同一文件”和“同一行”。在这种情况下,合并基础提交--就你的特定提交而言--是你的第一个提交,其中包含一个行为“Hello world!”的test.txt。两个分支提示具有其他内容的test.txt
从哲学上讲,定义“同一文件”是一个难题:参见忒修斯之船悖论。然而,Git只是宣布,如果文件test.txt存在于三个提交中——在合并基础中和两个分支提示提交中——那么这就是“同一文件”。所以这就清除了这个问题。但是,“同一行”仍然有点模糊。
从第一个提交到第一个分支提示提交所做的更改保持第1行不变,但修改了文件的结尾,添加了This is another line.
您对第一次提交和第二个分支顶部——合并之前的新master顶部所做的更改影响了第一行本身。
Git在更改区域的边缘有些混乱——有时实际上会在行之间发生更改。这些更改会涉及到上面和下面的行。最终,这只是算法决定更改是否冲突的怪癖:Git决定说这些更改确实触及到相同的行,而不同的算法可能会说它们没有。
(边缘效应源于必须具有非空间隔以避免篱笆帖子问题。各种算法主要使用半开区间:一个区域从符号X开始——行在此处充当符号——并在符号Y之前结束。文件的结尾通常为此目的分配一个EOF符号。一些算法还喜欢在第一行之上拥有一个符号,类似于文件的起始位置。)

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