它是逐行的,答案是肯定的和否定的:上下文确实很重要,但重要的数量却很棘手。它比你最初想象的要多和少。
您可能想先浏览this answer 到一个相关问题,作为背景。我现在假设我们将base 作为(单个)合并基础(也许我们通过标记特定提交来设置名称base,例如git tag base $(git merge-base HEAD <em>other</em>))和HEAD 作为我们在分支b1 上的提交,以及其他一些分支名称 b2 命名其他提交。
接下来,我们看看这两个差异:
git diff base HEAD
git diff base b2
如果我们看到文件 F 的所有三个版本都不同(因此 F 出现在两个输出中,并且更改不同),那么我们必须工作,在本质,diff-hunk-by-diff-hunk。在 diff hunks 重叠但做出不同更改的地方,Git 会声明冲突。但是——这似乎是你的问题——“做出不同的改变”究竟是什么意思?
我认为这是最好的例子。例如:
$ git checkout b1
[checkout messages here - but I was already on b1]
$ git diff base HEAD
diff --git a/basefile b/basefile
index df781c1..e4f9e4b 100644
--- a/basefile
+++ b/basefile
@@ -4,6 +4,7 @@
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
+# added line in b1
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
和:
$ git diff base b2
diff --git a/basefile b/basefile
index df781c1..c96620e 100644
--- a/basefile
+++ b/basefile
@@ -4,7 +4,6 @@
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
-# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
请注意,虽然这些更改不会触及 same 行,但从某种意义上说,它们也 确实 触及同一行。我添加了第 7 行(将旧第 7 行推到第 8 行),并删除了旧第 7 行。这些显然是“相同”行。所以:
$ git merge b2
Auto-merging basefile
CONFLICT (content): Merge conflict in basefile
Automatic merge failed; fix conflicts and then commit the result.
让我们中止此合并并考虑分支b3 的尖端(在我的设置中b1 和b3 的合并基础与b1 和b2 的合并基础相同)。
$ git merge --abort
$ git diff base b3
diff --git a/basefile b/basefile
index df781c1..e2b8567 100644
--- a/basefile
+++ b/basefile
@@ -5,7 +5,6 @@
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
$ git merge --no-edit b3
Auto-merging basefile
Merge made by the 'recursive' strategy.
basefile | 1 -
1 file changed, 1 deletion(-)
这一次没有冲突,尽管两个 diff hunks 触及了相同的一般区域。第二个差异删除了一个没有“接触”添加行的行,所以 Git 认为这是安全的。
如果您以同样的方式进行更多试验,您会确切地发现哪些看似重叠的更改被成功组合,哪些会导致冲突。显然,直接重叠的更改,例如,删除原始行 42 并插入不同的新行 42,将发生冲突。但是所有更改总是表示为“删除一些现有行,尽管可能为零”,然后是“添加一些新行,尽管可能为零”。 更改——即使是更改、添加或删除一行中的一个单词——删除非零数量的现有行并添加非零数量的新行。纯删除(一个或多个完整行)添加零行,纯插入删除零行。最后,归结为:“我们和他们的更改是否触及相同的行号?”上下文变得几乎无关紧要,除了在删除零行或插入零行时,上下文本身在某种意义上“就是”行。 (我不确定这种说法有多大意义,所以如果它难以理解,那是我的错。;-))
(还请记住,如果您在工作时修改“合并至今”文件,则在查看更改是否触及“相同”时,您必须使用 原始基本文件的行号行。由于“我们的”和“他们的”都有相同的基本版本,这是我们可以在这里使用的简单快捷方式。)
三路合并不是补丁
请注意,这与应用 patch 不同,后者是在没有通用基础版本的情况下完成的。在补丁的情况下,上下文被更多地使用:diff hunk 标头提供了搜索上下文的位置,但由于它可能应用于文件的不同版本,上下文允许我们(和 Git)只要上下文仍然匹配,在不同的行进行相同的更改。
patch 实用程序在这里使用了不同的算法(“最大模糊”因子,看起来 +/- 那么多行)。 Git 不做模糊因素;如果必须,它将一直搜索到文件的开头或结尾。但是,它确实具有在确定上下文不匹配之前调整空白的常用选项。
(当使用git apply 应用补丁时,您可以添加-3 或--3way 以允许Git 读取index 行,这些行提供文件blob 的部分或完整哈希ID。左侧哈希ID 是文件先前版本的哈希值:请注意,在上面的所有差异中,basefile 的“基本”版本的 ID 为 df781c1。如果 Git 可以从该 ID 中找到唯一的 blob,它可以假设那是合并基础,并且仅将一个合并基础与HEAD进行比较,将补丁本身视为其他 diff,并以这种方式进行三向合并。这有时允许@ 987654347@ 成功,patch 失败。)