假设我开始在 test.txt
中对 master 进行一次提交,只有一行 Hello world!
后跟一个新行(以防止在添加第二行时的第一行)。
然后,我使用分支名称 modification
分支此提交。这里我把文件从
Hello world!
到
Hello world!
This is another line.
然后我提交给那个分支。
然后我检查 master 并从
更改文件Hello world!
到
Hello world! This is a new thing.
然后我将其提交到master
。总之,在两次提交中,我只更改一行。由于我一开始在 master 上有换行符,因此 master
上的额外提交 仅 修改了第 1 行,而 modification
上的提交 only 修改第 2 行。因此,当我尝试将 modification
merge 到 master 时,我不明白为什么这会导致 merge 冲突。但是,我将其作为 diff3
输出。
<<<<<<< HEAD
Hello world! This is a new thing.
||||||| merged common ancestors
Hello world!
=======
Hello world!
This is another line.
>>>>>>> modification
为什么 git 没有意识到他们正在改变单独的行并将这两行 merge 在一起?我认为它需要对 master
上的提交进行第 1 行修改,对 modification
进行第 2 行修改以形成:
Hello world! This is a new thing.
This is another line.
我能想到的唯一可能性是,无论行号如何,都可以修改同一个大块。
有趣的是,如果我在 modifications
上添加 This is another line.
到第 3 行而不是第 2 行,将空行保留在 modification
分支, merge 连续无冲突。
最佳答案
您的想法是正确的:如果与 merge 基础提交中该文件的内容相比,Git 的两个“边”触及“同一文件”的“同一行”,则 Git 声明冲突。诀窍在于定义相同的文件 和相同的行。在这种情况下, merge 基础提交——给定你的特定提交,也就是说——是你有史以来的第一次提交,它有 test.txt
其中有一行,阅读 Hello world!
。这两个分支提示有test.txt
和其他内容。
从哲学上讲,定义相同的文件 是一个难题:参见the paradox of the Ship of Theseus .然而,Git 只是声明如果文件 test.txt
存在于所有三个提交中——在 merge 基础中,以及在两个分支提示提交中——那么这是“同一个文件”。这样就解决了这个问题。 😀 然而,“同一条线”还是有点模糊。
您从第一次提交到第一次分支提示提交所做的更改仅保留第 1 行,但修改了文件末尾,添加了 This is another line.
您从第一次提交到第二个分支提示所做的更改—— merge 前的新 master
提示——更改了第 1 行本身。
Git 在更改区域的边缘有点松鼠 — 实际上,更改有时会发生在之间行之间。这些变化触及上面和下面的线。最终,这只是选择决定更改是否冲突的算法的一个怪癖:Git 决定说这些更改确实触及相同的行,而不同的算法可能会说它们没有。
(边缘效应的产生是因为必须有非空区间,以避免栅栏柱问题。各种算法大多使用半开区间:一个区域从符号 X 开始——线作为符号,在这里——到符号 Y 之前结束。为此,文件末尾通常会分配一个 EOF 符号。一些算法喜欢在第一行“上方”也有一个符号,作为一种 SOF,或文件开始。)
关于git - 为什么更改相邻行但独立修改会导致 git merge 冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55275340/