简而言之,为什么文件foo.txt
具有内容
a
b
无法与包含foo.txt
内容的分支合并:
a
c
较长的版本是:试验Git和合并,我做了以下几点:
mkdir
新目录和cd
并git init
foo.txt
并添加第a
行(第一次就是这样,第二次是a
之后的2个空行)git checkout -b feature
和git checkout -b sprint
(据我所知,连续执行而不是先切换回master
并创建它并没有区别sprint
,因为分支是基于commitID创建的,两种情况都是完全相同的。git co feature
并使文件看起来像a
,然后清空行,然后在第三行c
git checkout sprint
并使文件看起来像a
,然后单独行b
。git merge feature
并且据说,合并可能已成功,内容
a
b
c
但为什么会失败?而不是猜测"也许线条太近了,可以从文档或参考文献中给出更明确的答案吗?
我还尝试在a
和b
之间以及b
和c
之间添加一个空行,以便它们更加间隔,但没有初始的空行foo.txt
的第一个版本,结果是相同的:合并冲突。
答案 0 :(得分:2)
Git检查行级别的差异。所以,让我们说你的文件的第一个版本是这样的:
a
现在,您在名为feature
的分支上创建该文件的第二个版本:
a
b
在此版本中,您更改了两行。为什么你会想到两条线?好吧,在\n
的末尾添加了换行符a
。
在分支sprint
中,您添加了该文件的另一个版本:
a
c
现在您修改了三行。
如果您现在尝试合并这两个修改,git会认识到您在两个提交中都更改了第1行和第2行,因此git不知道要采用哪个版本并且发生冲突。
答案 1 :(得分:2)
正如你所说,他们太近了。让我们使用一个没有空行的共同祖先来避免混淆。如果你有一些共同的祖先:
line 1
line 2
line 3
line 4
你编辑双方:
line 1
LINE TWO
line 3
line 4
和
line 1
line 2
LINE THREE
line 4
然后git diff / merge引擎(xdiff)将产生冲突。虽然我找不到这方面的文件,但显然可以凭经验看出来。这是一个实现细节,虽然是一个常见的细节。
如果您将automerge视为描述更改区域,描述与其他区域相关(而非线条,由数字处理),这可能更有意义:第一方在line 1
之后和{{之前更改数据1}}。第二方在line 3
之后和line 2
之前更改数据。
但是,当您尝试关联这些更改时,会遇到麻烦:第一方已删除了第二方依赖的上下文(line 4
)来描述其更改。
只要有一些上下文(即,更改不是"太近"),这应该有效,即使该上下文是单行。如果您的共同祖先是:
,请将您的示例扩展到不会立即更改相邻行的位置line 3
一方面是:
a
d
另一方是:
a
b
d
然后,这将成功自动充电:
a
c
d
答案 2 :(得分:1)
合并导致冲突,因为您在每个分支上都以几乎相同的方式修改了文件。 Git可能会尝试解决冲突本身,但因为它做出的任何决定都可能是错误的,它会让你这样做。
Git不会查看每行的更改内容。只更改或添加了一行。在一个分支中,您添加了一个新行,另一个分支添加了一个字符和一个新行。在两个分支中,您在第一个分支后立即添加一行,git希望您在合并时确定文件中应该包含哪一行。
您不会遇到冲突,因为git会在每个分支上看到文件中的独立更改。但是因为每个分支中的同一行都有变化,所以git会发生冲突并要求你解决。
答案 3 :(得分:0)
基本上对于git我相信每个具有不同历史的合并都是冲突。但它会尽力解决它自己的问题。它将尝试应用(使用git apply
)从diff到目标分支的文件的每个更改,但是当apply失败时,它将不再执行任何操作,它将让程序员解决它。
在您的文件中,在分支feature
中,您已将a\n\n
更改为a\n\nc
,并在分支sprint
中将a\n\n
更改为a\nb\nc
}。默认情况下,git空行和空格变化很重要。它无法决定应用哪种更改,因为它们既不同又相互矛盾。