我在分支foo
上,我想将develop
合并到我的功能分支foo
中。我希望自动解决所有冲突,并自动覆盖分支foo
中的任何代码。从分支foo
开始,我git merge -X theirs develop
有效。完成两次以进行双重检查后,我得到Already up-to-date
。
但是当我git rebase develop
确保foo
被抓住时,我会遇到合并冲突。为什么git merge -X theirs develop
合并时应该在分支develop
上包含所有更新的foo
代码?
答案 0 :(得分:3)
Rebase和merge做了很多不同的事情。
当你运行git merge develop
时,你告诉Git:
HEAD
)。这有一些哈希ID。develop
。这有一些哈希ID。跟踪提交图以查找步骤1和2中标识的两个提交的最低公共祖先合并基础提交:
...--o--B--o--1 <-- somebranch (HEAD)
\
o--o--2 <-- develop
比较(如git diff
)合并基础以提交#1。
-X theirs
有所不同的地方:如果两个差异中存在合并冲突,Git更喜欢“他们的”更改。请注意,对于单个文件的任何部分,显示两个不同但不冲突的更改,Git仍然进行两项更改。)将结果应用于合并库中的树。在当前分支上进行“merge commit”类型的新提交,父代#1和#2(按此顺序):
...--o--B--o--1---M <-- somebranch (HEAD)
\ /
o--o--2 <-- develop
如果您现在再次运行相同的git merge
,Git会找到M
和2
,找到它们的合并基础(这次不是B
而是2
}),并声明无事可做:合并基础已经是两个提交之一。
当你运行git rebase develop
时,你告诉Git:
列出当前分支提示(M
,在此合并完成后)可以访问的所有提交的列表,这些提交不能从{{1}标识的提交中到达(commit#2):
develop
我用...--o--B--o*-1*--M <-- somebranch (HEAD)
\ /
o--o--2 <-- develop
标记了这些提交。注意:*
也可以从M
到达,但不能从M
到达;但是2
故意抛弃所有合并,因为尝试重新合并是没有意义的。
使用“分离的HEAD”模式,复制(见下文)标记的提交,将新副本放在由名称git rebase
标识的提交之后:
develop
成功完成所有副本(包括解决任何合并冲突)后,从现在的任何位置删除 ...--o--B--o*-1*--M <-- somebranch
\ /
o--o--2 <-- develop
\
o*'--1*' <-- HEAD
标签,并将其放在复制的提交的末尾:
somebranch
要复制提交,Git基本上(有时是字面意思)在其上运行...--o--B--o--1---M [abandoned]
\ /
o--o--2 <-- develop
\
o'--1' <-- somebranch (HEAD)
。樱桃挑选操作本身就是合并的“动词类型”(有一种特殊的合并基础,而“我们的”和“他们的”可能会让人感到困惑,因为评论也是如此)。因此,对于要复制的许多提交,这些副本中的每一个都可能具有合并冲突。您在git cherry-pick
中所做的任何决议都会被忽略(当然,因为M
本身已被忽略)。