我正在使用git来跟踪我的LaTeX文档的更改.我倾向于将共同作者的反馈保留在一个单独的分支中,并在以后合并.到目前为止,事情似乎神奇地合并,但我想知道何时发生合并冲突,以便我可以在合并过程中获得一些真正的信任(我当然不希望文本出来时髦).
StackOverflow上有很多问题似乎都提出了同样的问题,但没有一个问题非常具体.例如,这个答案指定如果对同一个区域进行了更改就会发生冲突,但这让我想知道这些区域到底是什么.是仅仅对同一行进行了更改,还是考虑了某些上下文?
它是逐行的,答案是“否”和“是”:上下文固然重要,但是重要的是棘手的。它比起初您想的要多或少。
您可能想先略过相关问题的答案,以了解背景知识。现在,我假设我们base
以(单个)合并库为基础(也许我们base
通过标记特定提交(例如)来设置名称),并以其他分支名称命名另一个提交作为我们的提交。git tag base $(git merge-base HEAD other)
HEAD
other
接下来,我们看一下两个差异:
git diff base HEAD git diff base
如果我们看到文件F的所有三个版本都不相同(因此F在两个输出中都出现,并且更改也不同),那么我们就必须从本质上说是diff-hunk-by-diff-hunk。如果diff大块重叠,但进行了不同的更改,则Git声明发生冲突。但是-这似乎是您的问题-“进行不同的更改”到底是什么意思?
我认为这是最好的例子。例如:
$ 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
请注意,尽管这些变化不会触及同一线上,从某种意义上讲,他们也不要碰同一直线上,从某种意义上讲。我添加了第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大块头都碰到了相同的一般区域。第二个差异删除了没有“触及”添加的行的行,因此Git认为这是安全的。
如果您以相同的方式进行更多的实验,您将确切地发现哪些看似重叠的更改已成功组合,哪些导致了冲突。显然,直接重叠的更改(例如,如果两者都删除原始行42和插入不同的新行42)将发生冲突。但是所有更改始终表示为“删除一些现有行,尽管可能为零”,然后是“添加一些新行,尽管可能为零”。一项更改(甚至是仅更改,添加或删除一行中的一个单词的更改)会删除非零数量的现有行,并添加非零数量的新行。纯删除(一个或多个完整行)添加零行,而纯插入删除零线。最后,归结为:“我们和他们的更改是否都触及相同的行号?” 上下文几乎无关紧要,除了从某种意义上说,当删除零行或插入零行时,上下文本身就是这些行。(我不确定该说法有多大意义,因此,如果无法理解,那是我的错。;-)
(还请记住,如果您在工作时正在修改“到目前为止”的文件,则在查看更改是否触及“相同”行时,必须使用原始基本文件的行号。因为“我们的”和“他们的” ”具有相同的基本版本,这是我们可以在此处使用的快捷方式。)
请注意,这与应用补丁不同,后者无需启动通用基本版本即可完成。在补丁的情况下,上下文的使用要多得多:diff hunk标头提供了搜索上下文的位置,但是由于它可能会应用于文件的不同版本,因此上下文允许我们(和Git)只要上下文仍然匹配,就可以在另一行进行相同的更改。
该patch
实用程序在这里使用了不同的算法(“最大模糊”因子,看起来是+/-这么多行)。Git并没有模糊的因素。如果需要,它将一直搜索到文件的开头或结尾。但是,它确实具有通常的选项,可以在确定上下文不匹配之前调整空白。
(在使用git apply
补丁程序时,您可以添加-3
或--3way
允许Git读取index
行,这些行提供了文件Blob的部分或全部哈希ID。左侧的哈希ID是文件先前版本的哈希:请注意,上面所有的差异,都basefile
具有ID 的“基本”版本df781c1
。如果Git可以从该ID中找到唯一的Blob,则可以假装这是merge-base,并且仅对一个merge-base进行差异化HEAD
,从而处理补丁本身作为另一个差异,然后以这种方式进行三路合并。这有时可以git apply
在patch
失败的地方获得成功。)