为什么在Git中看似可以合并的代码会产生冲突?

3
简而言之,为什么一个名为foo.txt的文件有以下内容
a
b

无法与具有内容的 foo.txt 的分支合并:

a

c

更详细的版本是:为了尝试Git和合并,我做了以下操作:

  1. mkdir 新建一个目录,并进入该目录,然后 git init
  2. 创建一个文件 foo.txt,并添加一行内容 a(第一次就这样写,第二次在 a 后面加上两个空行)
  3. 提交它,现在执行 git checkout -b featuregit checkout -b sprint 命令(据我所知,连续执行命令与先切换回 master 再创建 sprint 的效果相同,因为分支是基于提交ID创建的,无论哪种情况,它们都完全相同)
  4. 现在执行 git co feature 命令,并将文件修改为 a,然后是一个空行,接着是第三行的 c
  5. 现在提交它,然后执行 git checkout sprint 命令,并将文件修改为 a,然后是下一行的独立字符 b
  6. 现在提交它,然后执行 git merge feature 命令

理论上,合并应该成功,并包含以下内容

a
b
c

为什么会失败呢?不要猜测“可能是行太接近了”,能否从文档或参考资料中得到更明确的答案呢?

我还尝试在ab之间以及bc之间添加空行,使它们更加分散,但是没有在foo.txt的第一个版本中添加初始空行,结果仍然是合并冲突。

4个回答

2

Git检查代码的区别是基于每一行的。假设你的第一个版本的文件看起来像这样:

a

现在,在名为“feature”的分支上创建文件的第二个版本:
a
b

在这个版本中,你改变了两行代码。你认为为什么要改变这两行代码呢?其实是在 a 的末尾添加了一个换行符 \n
在分支 sprint 中,你添加了该文件的另一个版本:
a

c

现在你修改了三行。

如果你尝试合并这两次修改,git会发现你在两个提交中都修改了第1行和第2行,因此git不知道应该采用哪个版本,会导致冲突的产生。


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)将产生冲突。虽然我没有找到相关文档,但这显然可以通过经验看出。尽管这是一个常见的实现细节,但它仍然是一个实现细节。
如果您将自动合并视为描述相对于其他区域(而不是由数字寻址的行)的更改区域,这可能会更有意义:第一侧在第1行之后和第3行之前更改数据。第二侧在第2行之后和第4行之前更改数据。
然而,当您尝试将这些更改进行关联时,就会遇到麻烦:第一侧已删除了第二侧用于描述其更改的上下文(line 3)。
只要有一些上下文(即更改不是“太接近”),即使该上下文只有一行,这也应该有效。为了扩展您的示例,以便您不会立即更改相邻的行,如果您的共同祖先是:
a



d

另一方面是:

a
b


d

另一方面是:
a


c
d

然后这将成功地自动合并为:
a
b

c
d

是的,我注意到如果将 bc 通过换行符分开得更远一些,它们就可以成功合并。 - nonopolarity

1
合并出现冲突,因为你们每个分支都以几乎相同的方式修改了文件。Git可以尝试解决冲突,但由于它做出的任何决定都可能是错误的,所以它会要求你来处理。
Git不会查看每行更改的内容,只会查看哪些行被更改或添加。在一个分支中,你添加了一行,在另一个分支中,你添加了一个字符和一行。在两个分支中,你都在第一行后面添加了一行,Git希望你确定在合并后应该保留哪一行。
如果每个分支中的文件独立更改,就不会出现冲突。但是由于每个分支上都有相同行的更改,Git会出现冲突并要求你解决。

原帖作者指出他的文件确实包含三行(a,后跟两个空格),并且这仍然是合并冲突。 - Edward Thomson

0

基本上,我认为对于Git来说,每个具有不同历史记录的合并都是一种冲突。但它会尽可能地通过自己的方式来解决这些冲突。它会尝试将差异中的每个更改应用(使用git apply)到目标分支的文件中,但当应用失败时,它将不再执行任何操作,并让程序员来解决。

在您的文件中,在分支feature中,您已将a\n\n更改为a\n\nc,而在分支sprint中,您已将a\n\n更改为a\nb\nc。默认情况下,Git认为空行和空格的更改是有意义的。它无法决定应该应用哪个更改,因为它们都是不同且冲突的。


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