1

我正在阅读这篇关于樱桃采摘的文章,那里有以下图片:

在此处输入图像描述

然而,这张照片对我来说似乎是一种误导。从我的简单测试来看,似乎不仅仅是差异,而是整个文件内容都被合并了。这是实验:我有这个提交图:

A--B
 \
  C

CommitA中有以下内容file.txt

l1
l2
l3

提交B有小的变化:

l1
l2-new
l3

提交C有小的变化:

l1
l2
l3-new

所以现在我正在尝试使用cherry-pick重播B提交,C

git cherry-pick B

我遇到了冲突,

<<<<<<< HEAD
l2
l3-new
=======
l2-3
l3
>>>>>>> C

如果仅应用更改,则不应该存在。由于我在提交中没有触及l2线C,它应该可以顺利应用。我对吗?

4

3 回答 3

5

Git存储文件,但它会在很多地方生成和使用差异。

Adiff记录提交前后受影响行的状态;它还存储修改区域前后的一行文本。Git使用此信息来避免数据丢失和不一致。

假设我们创建了名为 的分支AB并且C在您的描述中具有这些名称的提交上。

$ git diff A B -- file.txt
diff --git a/file.txt b/file.txt
index f0f2307..0acba21 100644
--- a/file.txt
+++ b/file.txt
@@ -1,3 +1,3 @@
 l1
-l2
+l2-new
 l3

我要求Gitfile.txt提交AB.

该格式是统一差异格式的一种变体,在 Wikipedia 页面上对diff utility.

简而言之,这diff表示:将文件的第 2 行从更改为l2l2-new但前提是第 1 行是l1并且第 3 行是l3。即使只更改了文件的第 2 行,Git也包括文件的第 1 行和第 3 行diff。它们是第 2 行发生的变化的上下文。

备注:在这种情况下,文件很小,第 1-3 行代表整个文件。Git不使用整个文件,它只保护更改前 1 行和更改后 1 行更改的任何行块。例如,如果文件有 20 行,我们更改第 12 和 13 行,则diff包含第 11-14 行。

回到我们的diff,提交C时文件的样子:

l1
l2
l3-new

但为了应用diff,Git期望它看起来像:

l1
l2
l3

因为它的期望没有得到满足,Git所以不能diff安全地应用并决定这是一个冲突。

为什么Git需要上下文行?

假设在提交时C我们删除了第二行。该文件将如下所示:

l1
l3

然后我们挑选 commit B,并应用它引入的更改(将第 2 行从 更改l2l2-new而不验证 context。该文件现在看起来像:

l1
l2-new

稍等!在哪里l3
我没有l3在提交时删除该行,C也没有在提交时触摸它B在不检查上下文的情况下应用差异可能会导致数据丢失。 Git总是在应用差异时检查上下文,我想所有使用差异的程序都这样做。

于 2015-01-15T11:07:04.493 回答
2

您最终会发生冲突,因为更改过于接近(它的行号方面)。上下文(通常是实际差异块周围的 3 行)需要匹配,否则 Git(和其他版本控制系统)会将更改标记为冲突。由于您的示例中的部分上下文发生了变化,因此它被标记为冲突。

于 2015-01-15T10:22:53.167 回答
0

Git 正在存储文件,而不是差异,所以 mb 由于行很接近,git 无法正确解析它。

于 2015-01-15T09:51:13.207 回答