繁体   English   中英

Git 中的合并是对称的吗?

[英]Are merges in Git symmetric?

假设我们有两个分支( BC )从一个共同的祖先A分出。 B合并到C 会产生与从C合并到B相同的结果吗?

  A
  |
 / \
B   C

澄清一下 - 我假设任何手动合并冲突解决方案都会在两个方向上发生。 但是发生的任何自动合并会导致选择相同的代码吗? 这就是我的假设,因为提交日期在两个方向上都是相同的。

进一步澄清 - 我知道实际合并会根据方向产生彼此的“镜像”。 我只是询问自动解决的冲突。

对于默认合并,答案是肯定的。 三路合并找到一个共同的祖先,然后应用双方的差异,这是一个不依赖于顺序的操作。 合并排序和可交换性的话题在git list上引起了一场引人入胜的讨论(如果你对这种事情感兴趣,那就是)。 注意B into CC into B应该是对称的,但对于(B into C) into AB into (C into A)不一定是相同的。

[编辑说明,2020 年 4 月:如果您添加-X ours-X theirs类的选项,答案将变为“否”,请参阅twalberg 的答案和其他人的答案以了解其他注意事项。]


详细说明一下,根据下面文斯的评论和 seh 对问题的评论, B into CC into B之间将有两个明显的差异,这两者都不会影响问题中引用的自动合并解决方案。

首先,历史会有所不同。 合并提交的父项将根据合并顺序发生变化。 对于这些示例,我将使用“first_branch”和“second_branch”,因此我可以保留字母来表示提交。

git checkout first_branch && git merge second_branch

E <- merge commit
|\
| D <- second_branch's tip
| |
| C <- another commit on second_branch 
| |
| B <- and another
|/
A <- first_branch's tip before the merge

在这种情况下, E 的“第一个父级” E^1是合并前 first_branch 的提示。 second_branch 是合并提交的“第二个父级”,又名E^2 现在考虑相反的情况:

git checkout second_branch && git merge first_branch

E <- merge commit
|\
| D <- first_branch's tip
| |
| C <- another commit on first_branch 
| |
| B <- and another
|/
A <- second_branch's tip before the merge

父母反了。 E^1是合并前 second_branch 的尖端。 E^2是 first_branch 的尖端。

其次,冲突的显示顺序会颠倒。 在第一种情况下,冲突可能如下所示:

<<<<<<< HEAD
This line was added from the first_branch branch.
=======
This line was added from the second_branch branch.
>>>>>>> second_branch

在第二种情况下,同样的冲突看起来像这样:

<<<<<<< HEAD
This line was added from the second_branch branch.
=======
This line was added from the first_branch branch.
>>>>>>> first_branch

这些差异都不会影响自动合并分辨率,但是当您反转三向合并顺序时,它们会出现。

这取决于您所说的“相同结果”是什么意思。 从内容的角度来看,假设不存在冲突,或者所有现有的冲突都以完全相同的方式精心解决,那么生成的新合并提交的内容应该是相同的。

但是,从历史拓扑的角度来看,两者是非常不同的。 如果您在分支 B 上并在 C 中合并,则 B 的 HEAD 移动到指向合并提交,但 C 保持原位。 相反,如果您在 C 上并在 B 中合并,则 C 的 HEAD 移动,而 B 保持原位。 所以最终的拓扑结构非常不同,这对任一分支的未来开发都有影响,即使新提交的内容在任何一种情况下都是相同的。

不,我认为它不会是对称的。 首先,您可以设置合并策略选项,特别是在您的情况下,决定是否选择 B 或 C 的是theirsours

在自动合并中,我认为例如,如果您要合并到您的更改中,远程分支的优先级高于您的更改,因此这意味着从 B 调用git merge C将导致选择 C ​​更改。 不过,我不是 100% 确定,所以您可以自己尝试并告诉我们。

内容是对称的,但是如果使用 GitHub 或 Bitbucket 或您喜欢的本地 Git 查看器查看合并时所做的更改,您会看到合并提交中列出的文件更改是不同的。 (以及上面提到的其他事情。)

git checkout b
git merge c

合并中显示的文件更改将是自bc分歧以来对c所做的更改。

git checkout c
git merge b

合并中显示的文件更改将是自bc分歧以来对b所做的更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM