问题描述
1 <- 2 <- 5 (merge commit) <- master <- HEAD
\ /
3 <-- 4 <- dev
- 在合并过程中,两种方式的合并仅使用提交
2
和4
吗?如果我是对的,那么在哪种情况下使用双向合并? - 什么是双向差异?
- 什么是三向差异?
- Is two way merge uses only commits
2
and4
during the a merge? If I am right, then in which situations a two way merge is used? - What is a two way diff?
- What is a three way diff?
推荐答案
我认为没有人真的在谈论双向差异".他们只是差异".在实践中,我也没有使用过三向差异",但是在版本控制中,它是一对差异的明显标签,该差异是从一个公共合并基础开始的,并查看了两个后续但发散的快照. (您可能还会查找"interdiff".请参见如何获取这两个git commit之间的interdiff?和 https://linux.die.net/man/1/interdiff .)
I don't think anyone really talks about "two way diffs"; they are just "diffs". In practice I don't see the phrase "three way diffs" used either, but in version control, it is the obvious label for a pair of diffs starting from a common merge base, looking at two subsequent but divergent snapshots. (You might also look up "interdiff". See How do I get the interdiff between these two git commits? and https://linux.die.net/man/1/interdiff.)
术语 merge 具有多种含义,并且在谈论 K向合并排序.但是,当涉及版本控制时(不仅仅是Git,它更具通用性),短语三种方式合并非常明确,指的是以 merge base 开头的合并版本,有两个不同之处.
The term merge has multiple meanings, and is (for instance, unrelated to Git) well-defined when talking about K-way merge sort. However, when it comes to version control (more general than just Git), the phrase three way merge is quite specific, and refers to a merge that starts with a merge base version, from which there are two divergences.
利用版本控制系统已定义三种方式合并"的事实,一些人做出了返回格式,将应用单个差异的过程称为双向合并".我认为这不是一个好术语,因为没有真正的合并正在进行.只需将其称为应用差异"或应用补丁"即可.
Using the fact that version control systems have defined "three way merge", some people have made a kind of back-formation to call the process of applying a single diff a "two-way merge". This is not a good term, in my opinion, as there is no real merging going on. Just call it "applying a diff" or "applying a patch".
另请参见为什么三向合并优于两向合并?请注意,所涉及的评论大约4或5方式合并实际上不适用于Git.
See also Why is a 3-way merge advantageous over a 2-way merge? Note that the comment that talks about a 4 or even 5 way merge is not really applicable to Git.
您可以使用git diff --full-index <commit1> <commit2> | git apply -3
使Git在单个文件上进行三向合并,其中每个文件的每个合并基础版本均从index
行中选择.但是,这本质上与选择与<commit1>
关联的所有文件作为合并基础相同.它的工作方式是git diff
在其输出中打印每个Blob的哈希ID,如果git apply
无法按原样应用补丁,Git将使用打印的Blob ID定位原始文件,然后计算从该合并基本版本到文件当前版本的第二个差异.然后将两个差异输入到合并机制中. (另请参见 git merge-file
命令但是请注意,每个文件在 <commit1>
中的blob哈希严格由附加到<commit1>
的 tree 对象确定.因此,这与说与<commit1>
关联的文件没有什么不同.也就是说,只有一个例外:Git具有提交哈希ID或对应的树ID,Git可以进行树范围的文件比较以查找重命名操作,然后Git可以将合并基础的文件路径关联为 P ,路径不同, P ,是本地"或文件.
You can use git diff --full-index <commit1> <commit2> | git apply -3
to make Git do three-way merges on individual files, where each merge base version of each file is selected individually from the index
line. However, this is essentially the same as choosing all the files associated with <commit1>
as the merge base. The way this works is that git diff
prints the hash ID of each blob in its output, and if git apply
is unable to apply the patch as-is, Git will use the printed blob ID to locate the original file, then compute a second diff from that merge base version to the current version of the file. It then feeds the two diffs into the merge machinery. (See also the git merge-file
command.) But note that the blob hash of each file in <commit1>
is determined strictly by the tree object attached to <commit1>
. This is therefore no different from saying the files associated with <commit1>
. That is, it's no different with one exception: if Git has the commit hash ID, or the corresponding tree ID, Git can do a tree-wide file comparison to look for rename operations, after which Git can associate the merge base's file path P with a different path P, the "local" or --ours
file.
换句话说,git diff --full-index <parent> <child> | git apply -3
和git cherry-pick <child>
之间的主要区别在于,前者在回退的三向修补"操作期间将不会检测到重命名,甚至不会尝试进行三向合并任何一个文件(如果能够执行此操作,则无需执行该操作).我认为,很难(但不是不可能)构建人为的示例,使它们产生非常不同的结果,但是我现在没有时间这样做.
In other words, the primary differences between git diff --full-index <parent> <child> | git apply -3
and git cherry-pick <child>
is that the former will not detect renames during the fall-back "three-way patch" operation, and will even not try a three-way merge on any one file if it's able to do the patch application without that. It is, I think, difficult (but not impossible) to construct artificial examples in which these produce very different outcomes, but I don't have time to do that right now.
事情在这里变得有些复杂,因为当前版本"不一定是HEAD版本.具体来说,git apply
使用工作树版本作为--ours
变体,而git apply --index
使用索引版本作为--ours
变体.但是,git cherry-pick
命令要求索引和工作树默认情况下是干净的",即与HEAD
提交匹配.在这种情况下,"HEAD版本",索引版本"和工作树版本"之间通常没有区别.
Things get a little complex here since "the current version" is not necessarily the HEAD version. Specifically, git apply
uses the work-tree version as the --ours
variant, while git apply --index
uses the index version as the --ours
variant. The git cherry-pick
command, however, requires that the index and work-tree be "clean" by default, i.e., match the HEAD
commit. In this case, there's normally no difference between "the HEAD version", "the index version", and "the work-tree version".
这篇关于什么是两种和三种方式的差异/合并?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!