Git章鱼多个分支的合并顺序

Posted

技术标签:

【中文标题】Git章鱼多个分支的合并顺序【英文标题】:Git octopus merge order of multiple branches 【发布时间】:2011-09-25 03:23:43 【问题描述】:

我在使用 git 时发生了一件有趣的事情,想知道是否有人可以向我解释一下,以便我更好地理解。

当合并多个分支(A,B)时,

git merge A B

失败为非快进,而

git merge B A

运作良好。为什么会这样?

【问题讨论】:

你遇到了什么样的冲突?我认为总的来说,这将是因为 B 所做的更改使 A 更容易合并,例如A 试图修补一个在 B 中重命名为该名称之前不存在的文件。 【参考方案1】:

假设 A 是当前分支的严格 direct child。然后假设 B 是 A 的严格直接子代

章鱼合并,processes heads given as arguments from left to right,相对于树递增,但相对于索引独立如果它尝试应用 B 和然后是 A,但如果它进行转换,则会遇到冲突。

根据git-merge 手册,合并策略部分

octopus
   This resolves cases with more than two heads, but refuses to do a
   complex merge that needs manual resolution.

例如:

 ~                 $ git init testdir && cd testdir && echo "This is C" > myfile
 Initialized empty Git repository in /home/huitseeker/testdir/.git/

 ~/testdir         $ git add myfile && git commit -m "C" 
 [master (root-commit) f0c8c82] C
  1 files changed, 1 insertions(+), 0 deletions(-)
  create mode 100644 myfile

 ~/testdir(master) $ git checkout -b "A" && echo "This is A1" > myfile
 Switched to a new branch 'A'
 ~/testdir(A)      $ git commit -m "A1" myfile
 [A ac5b51c] A1
  1 files changed, 1 insertions(+), 1 deletions(-)

 ~/testdir(A)      $ git checkout -b "B" && echo "This is B1" >> myfile
 Switched to a new branch 'B'
 ~/testdir(B)      $ git commit -m "B1" myfile
 [B 5bc838c] B1
  1 files changed, 1 insertions(+), 0 deletions(-)

 ~/testdir(B)      $ git checkout master
 Switched to branch 'master'
 ~/testdir(master) $ git merge B A
 Fast-forwarding to: B
 Already up-to-date with A
 Merge made by octopus.
  myfile |    3 ++-
  1 files changed, 2 insertions(+), 1 deletions(-)

 ~/testdir(master) $ git reset --hard HEAD^^^
 HEAD is now at f0c8c82 C
 ~/testdir(master) $ git merge A B
 Fast-forwarding to: A
 Fast-forwarding to: B
 error: Entry 'myfile' would be overwritten by merge. Cannot merge.
 Merge with strategy octopus failed.

 ~/testdir(master) $ cat myfile
 This is A1

确实,快进到A的时候,master的标签并没有被前推,虽然树已经前推了。

 ~/testdir(master) $ git status
 # On branch master
 # Changes to be committed:
 #   (use "git reset HEAD <file>..." to unstage)
 #
 #  modified:   myfile
 #

如果查看章鱼合并的代码,我手动执行此操作(查看上面的哈希):

 ~/testdir(master) $ git reset --hard f0c8c82
 HEAD is now at f0c8c82 C     
 ~/testdir(master) $ git read-tree -u -m f0c8c82 ac5b51c
 ~/testdir(master) $ git read-tree -u -m f0c8c82 5bc838c
 error: Entry 'myfile' would be overwritten by merge. Cannot merge.

在另一个方向(merge B A),现在,如果您再次查看 merge-octopus 的代码,它会尝试检测我们尝试添加的分支已经在树中(第二个 case for 循环)。事实上,在 A 的合并处,它看到 ac5b51c(又名 A 的头)是 A 和 B 的共同祖先,并且在没有执行第二个 read-tree 的情况下中止。

这种行为与 git 的新版本一致:虽然我指出了 v.1.3.1,但我的版本仍然会发生这种情况。

 ~/testdir(master) $ git --version
 git version 1.7.5.4

tl;dr : 你希望你的章鱼合并分支接触不同的文件

【讨论】:

您的链接并不能真正解释您所说的直接上游是什么意思。我最好的猜测是,您的意思是合并将是快进,即 B 是 A 的“严格、直接上游”意味着 A 是 B 的祖先。在这种情况下,您的示例不起作用。在第一种情况下,两个合并都是快进,一切都很好,在第二种情况下,第一个是快进,第二个已经合并,因此是无操作,不是合并冲突的原因。 你说得对,我说得太不准确了。我已经编辑了我的答案以反映您的 cmets,添加了章鱼不会在合并应用程序之间更新头部索引的关键指示,并包含一个最小示例。 太棒了,这就是答案。

以上是关于Git章鱼多个分支的合并顺序的主要内容,如果未能解决你的问题,请参考以下文章

git篇之Cherry-pick

git cherry 选择一系列顺序提交,包括合并

git中merge和rebase

git rebase 压缩提交

Git使用和代码管理

git 分支覆盖master分支