2014-02-11 44 views
1

我創建了一個新的分支,並開始在上面分行提交編輯

Z--A--B--C (master) 
      \-D--E (new-branch) 

工作然後我復位至編輯舊提交(A),同時仍然對new-branch和我的樹枝走散了

Z--A--B--C (master) 
\-A*--B--C--D--E (new-branch) (A* -> edited commit) 

我該如何將它們熔合回到以下狀態?壞變基之後

Z--A*--B--C (master) 
      \-D--E (new-branch) 

回答

2

其實,你所擁有的,重訂後是這樣的(我會拼他們B'等,而不是B*等,因爲這似乎是寫這些的更常見的方式):

Z - A - B - C <-- master 
    \ 
    A'- B'- C'- D'- E' <-- new-branch 

這是因爲必須複製複製每個舊提交(或更確切地說,複製大部分,除了已更改的位)以更改其中的任何內容,並且在修改提交A以生成A'之後,它必須複製和修改B,因爲新B'是不同的:B'A'作爲它的父母,rath呃比A。 (一切都是一樣的,但是改變父母需要做一個全新的提交,幸運的是提交非常小,他們只有父母,時間戳等等提交信息,並且一個SHA-1與「樹」關聯提交,和git可以重新使用舊樹。)

如果你想保持A'現在的方式有它出現在歷史master,你必須重新點master標籤在提交C'。這將「拋棄」提交C (這裏的ASCII藝術現在令人不安擁擠:-)):

Z - A - B - C  [abandoned] 
    \   .---------- master 
    A'- B'- C'- D'- E' <-- new-branch 

這也意味着,誰比誰此前見過你「發佈」(或「做廣告「)您的master意味着無論SHA-1提交C了什麼,都會看到您有」改寫歷史記錄「:提交C已不在畫面中,也不是B也不是A。相反,現在masterC',指向B',指向A',這點回Z

當然,對於new-branch也是如此:它用於指向E,但現在它指向E'

在另一方面,也許你並不真的想改變master。在這種情況下,您只有兩種選擇:完全放棄A',或者在提交Z後有masternew-branch分歧。

讓我們一起看看每個小組(除了最後一個選項,很簡單:什麼也不做,這就是你現在擁有的!)。


要重新點master,有兩個簡單的(ISH)方法:

  • 坐上分支,然後用git reset,這(在大多數操作模式)將改變提交到分支點:

    git checkout master 
    git reset --hard new-branch~2 # point master to commit C' 
    

    (像往常一樣與git reset --hard,在運行之前非常小心,你是在樹枝上要重新設置,一。d都沒有在樹枝上未保存在工作樹數據)

  • 雖然,使用git branch -f強行將其移動:

    git branch -f master new-branch~2 # point master to commit C' 
    

如果你不't想要移動master並確實想放棄A'並恢復舊的new-branch,有很多方法。假設你在現在和自底墊沒有做任何事情,特別REF-名ORIG_HEAD 將指向原始提交E。換句話說,我們可以得出這樣的原始底墊後情況更完整的畫面:

   D - E <-- ORIG_HEAD (copied from new-branch before rebase) 
      /
Z - A - B - C   <-- master 
    \ 
    A'- B'- C'- D'- E' <-- new-branch 

所以:

  • 如果你在new-branch想取消,你做rebase,git reset --hard ORIG_HEAD將會訣竅。 (照常使用--hard。)

  • 如果它爲太晚了,你可以找到提交您的reflogs E,並git reset --hard到原SHA-1,或者使用引用日誌的拼寫類似[email protected]{yesterday}[email protected]{3}或什麼的。

  • 如果你不介意複製D'E'又-新副本,D''E'',您可以使用--onto(這是我看到的是Magnus Bäck's answer底墊更長的形式,也得到了重新變基new-branch在此之前)。


的引用日誌將保留提交C了一段時間,所以回購將保留,直到引用日誌項過期提交。所以這完全不是放棄,或至少,還沒有。

這個ORIG_HEAD「特殊」參考是在您開始新的rebase時設置的,也可以是git merge之類的參數。如果您不確定,您可以使用git log ORIG_HEAD或類似的字詞來查看它實際指向的位置。

+0

感謝您的詳細解答,我終於'git reset --hard new-branch〜2' – olanod

2

你的實際情況是這樣的:

Z--A--B--C (master) 
\-A*--B*--C*--D*--E* (new-branch) 

現在,你可以使用引用日誌恢復新分支的前狀態,檢查出正確的分支,並執行變基。另一方面,你最終會得到相同狀態的分叉分支,所以...

你必須重新分支新分支。這很可能是由於爲這個簡單:

git rebase master 

Git會自動跳過應用提交B *和C *,因爲他們可能會最終爲空(除非犯了感動的代碼,他們還談到,在這種情況下,你」會發生衝突)。如果你想確保底墊中犯下d *和E *,限制其提交受到底墊和使用--onto

git rebase --onto master HEAD~2 

HEAD〜2是指C *和代表底墊的邊界操作,即我們將選擇D *和E *並將它們應用到主設備上。