2013-10-17 52 views
12

我有一个拉动请求,Github说它不能自动合并。这种改变背后掌握了一些提交,但没有冲突。Github无法合并分支,没有冲突,手动它自动合并

手动合并我没有得到任何冲突,我得到这个输出:

(on master) 
$git merge otherbranch 
[vim pops up for commit message, :wq] 
Auto-merging <file> 
Merge made by the 'recursive' strategy. 
<file> | 1 + 
1 file changed, 1 insertion(+) 

这就是为什么Github上不能自动合并?它总是自动地从命令行合并。这对Github来说不够自动吗?

回答

12

原因是git merge默认情况下使用了一种名为“递归”合并的策略。它能够执行三向合并:从一侧取得补丁,并将补丁应用到另一侧,以产生新文件。它也以递归方式执行此操作,在更复杂的情况下发生了很多分支和合并,并且有两个合并基础。

我最近遇到这个同样的情况:

$ git merge-base --all 90d64557 05b3dd8f 
711d1ad9772e42d64e5ecd592bee95fd63590b86 
f303c59666877696feef62844cfbb7960d464fc1 
$ 

随着2个合并基地,一个3路合并是不可能的。因此,“递归”的策略解决了这个由第一递归到这两个提交的合并:

$ git merge-base 711d1ad9 f303c596 
3f5db59435ffa4a453e5e82348f478547440e7eb 
$ 

OK,只有一个合并的基础,因此,合并3路就可以开始。两边有什么变化?

$ git diff --stat 3f5db594 711d1ad9 
normalize/coll.py  | 116 ++++++++++++++++++++++++++++++++++++++----------- 
normalize/visitor.py | 49 ++++++++++----------- 
tests/test_property.py | 10 +++-- 
3 files changed, 120 insertions(+), 55 deletions(-) 
$ git diff --stat 3f5db594 f303c596 
normalize/identity.py | 38 +++++++++++++++++++++++++++++++------- 
tests/test_property.py | 2 ++ 
2 files changed, 33 insertions(+), 7 deletions(-) 
$ 

这两个差异列表都修改了同一个文件,所以他们不能使用的只是把每个文件的较新版本从各侧(指数合并)一个简单的策略来解决。相反,git从一边取得新文件,然后尝试从另一面应用该补丁。其结果是一个组合的提交,这可以模拟这样的:

$ git checkout -b tmp 
Switched to a new branch 'tmp' 
$ git reset --hard f303c59666877696feef62844cfbb7960d464fc1 
HEAD is now at f303c59 record_id: throw a more helpful error if record identity is not hashable 
$ git merge 711d1ad9772e42d64e5ecd592bee95fd63590b86 
Auto-merging tests/test_property.py 
Merge made by the 'recursive' strategy. 
normalize/coll.py  | 116 ++++++++++++++++++++++++++++++++++++++----------- 
normalize/visitor.py | 49 ++++++++++----------- 
tests/test_property.py | 10 +++-- 
3 files changed, 120 insertions(+), 55 deletions(-) 
$ git diff --stat 3f5db594 HEAD tests/test_property.py 
tests/test_property.py | 12 +++++++++--- 
1 file changed, 9 insertions(+), 3 deletions(-) 
$ 

然后,它返回到原来的3路合并,使用该合并结果作为它的开始点;这也涉及到更改同一文件:

$ git diff --stat HEAD 90d64557| grep selector 
normalize/selector.py   | 17 +-- 
tests/test_selector.py   | 19 ++-- 
$ git diff --stat HEAD 05b3dd8f| grep selector 
normalize/selector.py | 29 +++++++++++++++++------------ 
tests/test_selector.py | 9 +++++++++ 
$ 

但是再次更改了文件的不同部分,并因此服用DIFF并将其应用到另一边是成功的。

因此,C git能够通过首先在两个起点的两个合并基础上进行3路合并,然后对两个原始提交进行另一个3路合并进行合并,第一次合并的中间结果。

Github的自动分辨率不会这样做。它并不一定是无能为力的,我不确定它实现了多少递归策略,但它在谨慎的方面却犯了错误,这正是你所期望的那样的一个大绿色按钮:-)。

+0

递归合并策略的好处。 +1对我自己的答案有很好的补充。 – VonC

5

不,这不是关于merging. It is about rebasing

你应该尝试变基,在当地的回购上的master顶部(克隆的your fork),otherbranch

首先,确保主是从原来的上游回购最近的一次:

fork

cd /your/local/repo 
git remote add upstream /url/original/repo 
git fetch upstream 

# Make sure you don't have any local commmit on your master 
git branch -f master upstream/master # reset your master branch 
            # to the one from upstream repo 
git checkout otherbranch 
git rebase master 

这变基会产生冲突,你应该解决,git add,然后git rebase --continue

最后,只需push --force你的分支到你的叉:将更新您的拉动请求自动(闲来无事)。

git push -u -f otherbranch origin 

(如果它已经被按下一次,单独git push应该足够)

more tips about pull-requests here

+0

好的,我认为这是有道理的。谢谢! – jpimentel

0

默认情况下,在确认合并提交的提交消息之前,Git不知道它是否可以自动合并您的分支。

如果你知道你不会有任何冲突,你可以通过改变GIT_EDITOR到非交互工具,例如通过增加cattrue自动递归自动合并的过程:

GIT_EDITOR=true git merge otherbranch 

pull也一样。您还可以指定合并策略,如-X theirs-X ours

或另一种方法是变基(添加-r到您pull命令)。