为什么使用Git看似可能的合并有冲突?

时间:2014-05-20 14:59:47

标签: git

简而言之,为什么文件foo.txt具有内容

a
b

无法与包含foo.txt内容的分支合并:

a

c

较长的版本是:试验Git和合并,我做了以下几点:

  1. mkdir新目录和cdgit init
  2. 创建一个文件foo.txt并添加第a行(第一次就是这样,第二次是a之后的2个空行)
  3. 提交它,现在git checkout -b featuregit checkout -b sprint(据我所知,连续执行而不是先切换回master并创建它并没有区别sprint,因为分支是基于commitID创建的,两种情况都是完全相同的。
  4. 现在git co feature并使文件看起来像a,然后清空行,然后在第三行c
  5. 现在提交,并git checkout sprint并使文件看起来像a,然后单独行b
  6. 现在提交它,现在执行git merge feature
  7. 并且据说,合并可能已成功,内容

    a
    b
    c
    

    但为什么会失败?而不是猜测"也许线条太近了,可以从文档或参考文献中给出更明确的答案吗?

    我还尝试在ab之间以及bc之间添加一个空行,以便它们更加间隔,但没有初始的空行foo.txt的第一个版本,结果是相同的:合并冲突。

4 个答案:

答案 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空行和空格变化很重要。它无法决定应用哪种更改,因为它们既不同又相互矛盾。