Git章鱼合并多个分支的顺序 [英] Git octopus merge order of multiple branches
问题描述
我使用git发生了一件有趣的事情,想知道是否有人可以向我解释,这样我可以更好地理解。
在合并多个分行(A,B)时,
git merge AB
失败为非快进,而
git merge BA
好。为什么会这样?
假设A是严格的, direct child 。然后假设B是一个严格的直接子 A 。
章鱼合并,处理由左至右的参数,如果它试图应用B然后A,但是如果它进行了转换,则会遇到冲突,但是如果它试图应用B然后A,那么对于索引独立于索引成功地不会发生冲突。
$ b
根据 git-merge
手册, MERGE STRATEGIES部分:
octopus
这样可以解决两个以上头的情况,但拒绝执行需要手动解析的
复杂合并。
例如:
〜$ git init testdir&& cd testdir&&回声这是C> myfile
/home/huitseeker/testdir/.git/
$ b〜/ testdir $ git add myfile&&&& git commit -mC
[master(root-commit)f0c8c82] C
1个文件已更改,1个插入(+),0个删除( - )
创建模式100644 myfile
〜/ testdir(master)$ git checkout -bA&&回声这是A1> myfile
切换到新分支'A'
〜/ testdir(A)$ git commit -mA1myfile
[A ac5b51c] A1
1个文件已更改,1插入(+),删除1个( - )
〜/ testdir(A)$ git checkout -bB&&回声这是B1>> myfile
切换到新分支'B'
〜/ testdir(B)$ git commit -mB1myfile
[B 5bc838c] B1
1个文件已更改,1插入(+),0删除( - )
〜/ testdir(B)$ git checkout master
转换到分支'master'
〜/ testdir(master)$ git合并BA
快速转发到:B
已经与A
合并,章鱼合并。
myfile | 3 ++ -
1个文件已更改,2个插入(+),1个删除( - )
〜/ testdir(主)$ git reset --hard HEAD ^^^
HEAD现在位于f0c8c82 C
〜/ testdir(master)$ git合并AB
快速转发到:A
快速转发到:B
错误:条目'myfile '会被合并覆盖。无法合并。
与策略章鱼合并失败。
〜/ testdir(master)$ cat myfile
这是A1
实际上,当快速转发到A时,虽然树已经有了,但是master的标签还没有被推送。
〜/ testdir(master)$ git status
#在分支主机上
#要提交的更改:
#(使用git reset HEAD< file> ...
#
#modified:myfile
#
在章鱼合并的代码中,我手动执行这个操作(看上面的哈希):
〜/ testdir(master )$ git reset --hard f0c8c82
HEAD现在在f0c8c82 C
〜/ testdir(master)$ git read-tree -u -m f0c8c82 ac5b51c
〜/ testdir(master)$ git read-tree -u -m f0c8c82 5bc838c
错误:条目'myfile'将被合并覆盖。无法合并。
在另一个方向( merge BA
)现在,如果再看一下merge-octopus的代码,它会尝试检测我们要添加的分支是否已经在树中(第二个 case
> for
loop)。的确,在A合并时,它看到ac5b51c(又名A的头)是A和B的共同祖先,并且在没有执行第二个读取树
的情况下放弃。 p>
这种行为与新版本的git一致:虽然我已经指出v.1.3.1,但这仍然在我的版本中发生。
〜/ testdir(master)$ git --version
git版本1.7.5.4
tl; dr:您希望章鱼合并分支触及不同文件
I had an interesting thing happen using git, wondering if anyone could explain it to me so I can understand better.
When doing a merge of multiple branches (A,B),
git merge A B
fails as non-fast-forward, while
git merge B A
worked well. Why would that be?
Let's assume that A is a strict, direct child of the current branch. Then assume that B is a strict, direct child of A.
The octopus merge, which processes heads given as arguments from left to right, incrementally with respect to the tree, but independently with respect to the index succeeds without conflict if it tries to apply B and then A, but encounters a conflict if it does the convert.
As per the git-merge
manual, section MERGE STRATEGIES:
octopus
This resolves cases with more than two heads, but refuses to do a
complex merge that needs manual resolution.
For instance:
~ $ 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
Indeed, when fast-forwarding to A, the label of master has not been pushed forward, though the tree has.
~/testdir(master) $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: myfile
#
If, looking at the code of what the octopus merge does, I perform this manually (look above for hashes):
~/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.
In the other direction (merge B A
), now, if you look again at the code of merge-octopus, it tries to detect the branch we are trying to add is already in the tree (second case
of the for
loop). Indeed, at the merge of A, it sees ac5b51c (a.k.a. A's head) is the common ancestor of A and B, and aborts without doing the second read-tree
.
This behavior is consistent with the fresh version of git : though I've pointed to v.1.3.1, this is still happening with my version.
~/testdir(master) $ git --version
git version 1.7.5.4
tl;dr : you want your octopus merge branches to touch distinct files
这篇关于Git章鱼合并多个分支的顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!