2013-10-17 97 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命令)。