2010-04-22 221 views
4

我知道this問題,但不確定如何將其映射到我目前的情況。 (再次基於是可怕的,撤銷重訂爲雙嚇人!)從多個git rebases恢復「舊提交」

我開始了我的主人的幾個不同的特性分支:

master x-x-x-x-x-x-x-x-x-x 
      \  \ \ 
FeatureA  1-2-3 \ \ 
FeatureB    A-B \ 
FeatureC      X-Y-Z 

我想他們都合併在一起,並檢查它們合併返回到以前工作大師的頂部,所以我做了:

git checkout FeatureB 
git rebase FeatureA 
git mergetool //etc 
git rebase --continue 

然後

git checkout FeatureC 
git rebase FeatureB 
git mergetool //hack hack 
git rebase --continue 

這給我留下了

master x-x-x-x-x-x-x-x-x-x 
      \ 
FeatureA  1-2-3 
        \ 
FeatureB   A'-B' 
         \ 
FeatureC     X'-Y'-Z' 

然後我糾正一些位未正確編譯,並得到了全功能設置爲可接受的狀態:

master x-x-x-x-x-x-x-x-x-x 
      \ 
FeatureA  1-2-3 
        \ 
FeatureB   A'-B' 
         \ 
FeatureC     X'-Y'-Z'-W 

我的問題是,我的同事告訴我,我們還沒有準備好FeatureA。

有沒有什麼方法可以讓我保留所有的工作,還可以恢復到可以將FeatureC轉換到Feature B的情況?

+0

實際上,我感到困惑,爲什麼你重建基礎可言。您應該已經創建了一個與master或featureC關聯的新分支(稱爲featuresABC),然後將它們合併到其中,從而使功能分支完好無損。保留各種功能分支的獨立歷史是很好的。 – Cascabel 2010-04-22 15:47:20

+1

@Jefromi,因爲我還在學習...... – Benjol 2010-04-22 18:55:59

+0

@Jefromi,如果你想檢查(甚至自己聲稱) – Benjol 2010-04-23 06:37:45

回答

4

這就是我的答案是什麼的認識,基於評論:

當你做一個底墊中,你目前的提交分支'是'撤消',然後'重新申請',但實際上,他們沒有撤消,他們被'記住'*,並重新申請新的ID,例如,如果我看看git reflog show FeatureB,我得到這樣的事情:

7832f89 [email protected]{0} rebase finished: refs/heads/FeatureB onto f4df3 
efd3fed [email protected]{1} commit: B 
f3f3d43 [email protected]{2} commit: A 
2f32fed [email protected]{3} branch: Created from HEAD 

正如@Jefromi所說,原件仍然存在(A和B在reflog中提交的SHA與在git log中提交的不一樣,對應於A'和B')。

同樣,git reflog show FeatureC看起來像這樣

32873ef [email protected]{0} commit: W 
17dafb3 [email protected]{1} rebase finished: refs/heads/FeatureC onto 89289fe 
893eb78 [email protected]{2} commit: Z 
a78b873 [email protected]{3} commit: Y 
e78b873 [email protected]{4} commit: X 
378cbe3 [email protected]{5} branch: Created from HEAD 

同樣,原來Z,Y和X提交仍然存在

所以,解決我的問題是創建一個新的分支FeaturesBC關閉主的HEAD(例如),那麼櫻桃挑提交FeatureB {2 & 1},然後FeatureC {4,3,2},和(可能的)W:

git checkout master 
git checkout -b FeaturesBC 
git cherry-pick f3f3d43 
git cherry-pick efd3fed 
//etc... 

(這似乎已經奏效,我不得不重新做一些相同的合併的,但它不是太糟糕了)

編輯,從Jefromi:

挑肥揀瘦可能沒有必要。你也可以簡單地重建分支,其中的分支是底墊前:

git branch FeatureB-old efd3fed 
git branch FeatureC-old 893eb78 

或者,如果你想扔掉FeatureB和FeatureC的重訂基位置,回到原來的位置前:

git branch -f FeatureB efd3fed 
git branch -f FeatureC 893eb78 

最後,請注意,如果您喜歡,您可以使用reflog中提供的其他表示法 - 例如,[email protected]{2}而不是893eb78。這意味着「FeatureC的第二個以前的位置」。不過,請注意在查看reflog後立即使用它,因爲只要再次更新分支(移動它,提交給它...),[email protected]{2}將代替17dafb3。

由於@Jefromi評論我的問題:

你或許應該已經創建了一個新的分支關老爺或featureC(稱爲featuresABC,說),以及合併每個進去,留下功能分支完好。保留各種功能分支的獨立歷史是很好的。

*確切地說,舊的提交對象只留在版本庫中。他們最終會被修剪,因爲你不希望回購充滿舊的懸掛承諾;這將在第一次運行git gc時發生並且提交至少兩週(由gc.pruneExpire配置)。

0

如果一切都失敗了,你可以重新啓動master和git cherry-pick所有的B或C都承諾重新創建這些分支。我希望別人已經寫了一個腳本,如果這是唯一的解決辦法...

+0

嗯,說實話,我在開始之前備份了我的整個資源庫,所以我並沒有完全搞砸,但我想避免再次重做整個rebase的事情...... – Benjol 2010-04-22 13:18:07

+0

我的理解(從這裏http: //Backoverflow.com/questions/2689634/do-i-need-to-perform-a-commit-after-a-rebase)是B和C的提交已被rebase修改,所以這是行不通的,或者我錯過了什麼? – Benjol 2010-04-22 13:19:36

+0

@ Benjol:你是部分正確的:重新提交的提交確實是原始版本的修改版本(具體來說,它們有不同的父母,可能有些不同的補丁),但原始文件仍然存在。找到它們的最簡單方法可能是'git reflog show FeatureA' - 這比通過HEAD'的reflog拾取並確定哪些線屬於哪個分支要容易一些。 – Cascabel 2010-04-22 15:44:05

0

您可以使用git rebase --onto <old-merge-base from B> A C將從C到A的所有內容重新組合到主節點上。它會留給你:

master x-x-x-x-x-x-x-x-x-x 
      \  \ 
FeatureA  1-2-3 \ 
         \ 
FeatureB    A'-B' 
          \ 
FeatureC      X'-Y'-Z'-W 

找到點要重訂到,還可以使用Git的引用日誌和git merge-base的組合 - 但你也可以變基到A的合併基礎,有歷史類似以下內容:

master x-x-x-x-x-x-x-x-x-x 
      |\ 
FeatureA | 1-2-3 
      \ 
FeatureB  A'-B' 
        \ 
FeatureC    X'-Y'-Z'-W 

git rebase --onto $(git merge-base A master) A C

+0

這當然是所有的工作,但只要舊的非基礎提交是仍然在儲存庫中,不需要重新分配。 (給出錯誤的機會更多,不必要地刷新提交日期。) – Cascabel 2010-04-23 20:29:37