2012-03-01 75 views
7

使用git v1.7.1我試圖同時對--preserve-merges--onto功能進行重新綁定。最終結果似乎沒有合併提交,因此看起來是線性的。我寧願保留合併提交,原因與人們經常使用--preserve-merges(更容易看到邏輯上是一個單獨功能並在其自己的分支中開發的提交組)相同。git rebase「--preserve-merges --onto」不保留合併

我的主分支(目標爲底墊)很無聊:

A-B-C

的特性分支我想從拿有已被合併到其子特性分支。像:

 X - Y 
/ \ 
V-W ------ Z 

其中Z是一個合併提交是特性分支的負責人,從拿地,X和Y分別在子特性分支。

我使用:git rebase --preserve-merges --onto C V Z

我想直到結束:

  X - Y 
     / \ 
A-B-C-W ------ Z 

但不是我越來越:

A-B-C-W-X-Y 

,由於Z是一個受衝突自由合併,代碼的最終狀態是正確的,但歷史並不像我想的那樣富有表現力。

有沒有辦法得到我想要的東西?

編輯地址@Bombe: 我寫了一個bash腳本來構造我的例子。在我的系統上(使用git 1.7.1的RHEL 6.2),這證明了我的問題。

#! /bin/bash 
# start a new empty repo 
git init 
# make some commits on the master branch 
git checkout master 
touch A.txt; git add A.txt; git commit -m "add A.txt"; git tag Atag 
touch B.txt; git add B.txt; git commit -m "add B.txt"; git tag Btag 
touch C.txt; git add C.txt; git commit -m "add C.txt"; git tag Ctag 
# now build the feature branch 
# start at Btag (more or less arbitrary; point is it's before C) 
git checkout Btag 
git checkout -b feature 
touch V.txt; git add V.txt; git commit -m "add V.txt"; git tag Vtag 
touch W.txt; git add W.txt; git commit -m "add W.txt"; git tag Wtag 
# now a subfeature 
git checkout -b subfeature 
touch X.txt; git add X.txt; git commit -m "add X.txt"; git tag Xtag 
touch Y.txt; git add Y.txt; git commit -m "add Y.txt"; git tag Ytag 
# merge the subfeature into the feature 
# preserves branch history with --no-ff 
git checkout feature 
git merge --no-ff subfeature 
# the merge commit is our Z 
git tag Ztag 
# one more commit so that merge isn't the tip (for better illustration of Z missing later) 
touch postZ.txt; git add postZ.txt; git commit -m "add postZ.txt"; git tag postZtag 
# now do the rebase 
git rebase --preserve-merges --onto Ctag Vtag 
# optionally move the master branch forward to the top of feature branch 
git checkout master 
git merge feature 

底墊之前,我:

 X-Y 
    / \ 
    V-W-----Z-postZ 
/
A-B-C 

底墊後,我得到:

 X-Y 
    / \ 
    V-W-----Z-postZ 
/
A-B-C-W'-X'-Y'-postZ' 

注意缺少的Z和postZ」 'Y' 之間。

回答

10

非常感謝Bombe和一位離線朋友指出這對一些人有用。憑藉這種靈感,我現在能夠回答我自己的問題。

簡短回答:1.7.5.2之前的git版本會顯示這種不良行爲。

很長的回答:在git自己的源代碼回購中,2011年4月28日提交c192f9c865dbdae48c0400d717581d34cd315fb8明確解決了這個問題。

引述提交的信息(由安德魯·黃):

git-rebase--interactive.sh: preserve-merges fails on merges created with no-ff 

'git rebase' uses 'git merge' to preserve merges (-p). This preserves 
the original merge commit correctly, except when the original merge 
commit was created by 'git merge --no-ff'. In this case, 'git rebase' 
will fail to preserve the merge, because during 'git rebase', 'git 
merge' will simply fast-forward and skip the commit. For example: 

       B 
      /\ 
      A---M 
      /
    ---o---O---P---Q 

If we try to rebase M onto P, we lose the merge commit and this happens: 

       A---B 
       /
    ---o---O---P---Q 

To correct this, we simply do a "no fast-forward" on all merge commits 
when rebasing. Since by the time we decided to do a 'git merge' inside 
'git rebase', it means there was a merge originally, so 'git merge' 
should always create a merge commit regardless of what the merge 
branches look like. This way, when rebase M onto P from the above 
example, we get: 

        B 
       /\ 
       A---M 
       /
    ---o---O---P---Q 

解決方案:得到的git的新版本,如果需要從源代碼構建。

順便說一句,我用git bisect來解決這個問題。真棒工具。

0

我剛剛嘗試重新創建您的情況,並且我可以報告--preserve-merges似乎按照廣告方式工作。當您提交Z時,只需發出:

git rebase --preserve-merges --onto C V 

這就是我所做的,它保留了合併提交。

+0

我編輯了原始帖子,提供重現我的問題的步驟。我相信你是對的,但我不明白我做錯了什麼。 – RaveTheTadpole 2012-03-01 23:03:50

+2

我確實有一個大於1.7.5.2的版本。 :) – Bombe 2012-03-02 06:11:38

1

我遇到了這個問題。注意我的git版本,它是1.7.10.2。

我正在做一個提交範圍(通過它的SHA1散列標識)到一個分支的rebase,也缺乏最後的合併提交。

我的解決方案是將W重新設置爲X到C(不保留合併),然後將Y,Z和postZ重新綁定到X'上。

希望這會有所幫助。