假设我从test.txt
中的master提交一次开始,仅在行Hello world!
之后加上新行(以防止在添加第二行时在第一行发生任何差异)。 / p>
然后,我使用分支名称modification
分支此提交。在这里,我从
Hello world!
到
Hello world!
This is another line.
,然后我进入那个分支。
然后我检出master并从
更改文件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
的提交到第1行的修改以及从modification
到第2行的修改才能形成:
Hello world! This is a new thing.
This is another line.
我能想到的唯一可能性是,不管行号如何,都可以修改相同的块。
有趣的是,如果我在modifications
上将This is another line.
添加到第3行而不是第2行,则将空行保留在modification
分支上,则合并将连续进行而不会发生冲突。
答案 0 :(得分:2)
您有一个正确的想法:与合并基础提交中该文件的内容相比,如果两个“边”都触摸“相同文件”的“相同行”,则Git声明冲突。诀窍在于定义相同文件和相同行。合并基础提交是您有史以来的第一个提交,其中有test.txt
,其中有一行,读为Hello world!
。这两个分支技巧的其他内容包含test.txt
。
从哲学上讲,定义相同文件是一个难题:请参阅the paradox of the Ship of Theseus。但是,Git仅声明如果文件test.txt
存在于所有三个提交中(在合并基础中以及两个分支提示提交中),则该文件为“同一文件”。这样就可以立即解决该问题。但是,“同一条线”仍然有点模糊。
您从第一次提交到第一个分支提示的更改只提交了第1行,但修改了文件的末尾,添加了This is another line.
您从第一次提交到第二个分支提示所做的更改(合并前的新master
提示)更改了第1行本身。
Git在更改区域的边缘有点松散,实际上,更改发生在 行之间。这些变化触及上一行和下一行。最终,这只是决定变化是否冲突的算法的古怪之处:Git决定说这些变化确实触及同一条线,而不同的算法可能会说它们不触碰。
(边缘效应是由于必须具有非空的间隔而产生的,以避免栅栏问题。各种算法大多使用半开间隔:一个区域从符号X开始(在这里线条充当符号,在符号Y之前结束)。为此,通常为文件的末尾分配一个EOF符号。某些算法也喜欢在第一行的上方也有一个符号,例如SOF或“文件开始”。)