2017-08-01 73 views
0

讓我們假設一個功能分支被合併到主控後被刪除。如何重新創建合併的Git分支

幾天/幾周後,我需要爲該功能分支中的所有提交生成補丁文件。

如果我周圍的特性分支,我可以使用下面的命令生成補丁:

git format-patch $(git merge-base master my_feature_branch)..my_feature_branch 

那麼,如何我可以重新創建功能分支,所以我可以用上面的命令?

+0

一種不尋常的問題;所以你*知道*你需要向他人提供一個描述該分支發生的所有事情的補丁,但是你不記得什麼時候開始了? –

+0

你想知道如何*找到*功能分支中最新提交的提交,或者在找到該提交後如何創建分支*? – mkrieger1

回答

3

那麼,首先,分支並不真正被刪除。只有分支名稱被刪除。但是這讓我們陷入了一個棘手的問題:What exactly do we mean by "branch"?

讓我們快速看看合併過程。我們開始了一系列在提交的提交圖形(或「DAG」;見鏈接的問題)看起來像這樣:

...--o--*-----o <-- master 
     \ 
      o--o--o--o--o <-- feature 

我們然後運行:

git checkout master 
git merge feature 

這在某種程度上數字從我們最後一次合併他們(這實際上從來沒有,但他們在一起,在這裏標記爲*這一點),我們已經在masterfeature兩者中改變了。混帳然後作出新合併提交回指向這兩個分支的頂端的承諾:

...--o--*-----o---------o <-- master 
     \   /
      o--o--o--o--o <-- feature 

,我們有「合併」:提交,類型合併的提交

我們現在可以刪除單詞feature和箭頭,即刪除名稱。該保持不變,由名master保留:

...--o--*-----o---------M <-- master 
     \   /
      o--o--o--o--F 

如果我們希望看到通過feature走進master,我們所要做的就是找到犯我已經標記F(用於功能)在這裏。請注意,我還標記了合併提交M(用於合併)。

找到它的方法是從master開始,向後找,直到找到M。 (它現在就在master的頂端,儘管後來它會從尖端返回一些步驟。)然後,我們只需看M第二個父提交

要找到我們知道其哈希ID的提交的第二個父代,我們只需告訴Git:告訴我此另一個哈希ID的第二個父代的哈希ID。簡單的方法是使用git rev-parse。讓我們說的M哈希ID是badf00d

git rev-parse badf00d^2 

的Git吐出的F完整哈希ID。帽子二後綴意味着「第二父母」(帽子一,或者僅僅是帽子,意思是「第一父母」)。

現在我們可能還想找到提交*。這就是合併基地的提交,它是的第一個的父代M,以及我們剛發現的這個特定提交F。要查找兩次提交的合併基礎,我們要問的Git:

git merge-base badf00d^1 badf00d^2 

然後,我們可以看看每一個承諾的範圍開始剛過合併基礎*並通過不斷上升,包括犯F,使用git loggit format-patch管他呢。

我們可以使用原始哈希做到這一點,或者我們可以點名稱(暫時性或永久性的,他們將生活,只要完全按照自己喜歡的),以提交MF,和/或*,使用git branchgit tag。每個名稱都會記住您的哈希ID。標籤名稱和分支名稱之間的主要區別在於,如果您的標籤名稱爲git checkout,則會得到「分離的HEAD」並且不在分支上,但如果您的分支名稱爲git checkout,則會在該分支上獲得,如果你讓提交,否則將導致該分支前進:

$ git branch newname <hash-ID-of-commit-F> 

...--o--*-----o---------M--o--o--o <-- master 
     \   /
      o--o--o--o--F <-- newname 

$ git checkout newname 
... hack away ... 
$ git commit ... 

...--o--*-----o---------M--o--o--o <-- master 
     \   /
      o--o--o--o--F--o <-- newname (HEAD) 

這是所有分支,Git中:在只是點提交,而分支結構,歷史或DAGlet或任何你想要的名字,都是由提交DAG的永久部分組成的。分行名稱具有特殊功能,您可以git checkout他們,並通過運行git commit使他們前進。

+0

非常有用的信息。我瞭解涉及在合併分支中查找提交的各種命令。到目前爲止,我已經使用IDE或'tig'來查找它們。組織中廣泛使用的工具需要分支名稱作爲輸入。看起來像一種選擇是編寫一個腳本,該腳本將查找提交F和*(以M作爲輸入),從*創建分支並且櫻桃選擇*和F之間的範圍(包括)。如果分支命令支持通過這種方式創建分支的選項,我會很高興:)謝謝 – akirekadu

+1

順便說一下,我不完全清楚爲什麼你要重新複製通向F的提交。您可以創建一個指向提交'F'的新分支名稱,按名稱檢出新分支,並在該分支上進行新的提交。 – torek

+0

傳統工具。他們使用給定分支和主人之間的git merge-base來爲分支中的所有提交生成補丁。關閉F創建分支不會返回*作爲合併基礎。 – akirekadu

0

如果你有一個基地提交,從現在刪除的特性分支已經發散的一個,你可以繼續像如下 -

  1. 退房基於從底座提交一個分支。
  2. 使用git cherry-pick,櫻桃選擇合併提交已合併到主功能分支。如果這不起作用,您可以選擇屬於功能分支的單個提交。
1

讓我們假設以下簡化歷史記錄:功能分支基於提交N幷包含提交PQ。同時,提交O已添加到主分支。功能分支合併在提交R中。之後,創建了ST,這是現在的主人。

M -- N -- O -- R -- S -- T [master] 
     \  /
     P --- Q 

您想查找提交Q。我不認爲有這樣的編程方式,所以您需要使用任何存儲庫瀏覽器,例如gitk

一旦你找到Q,你可以很容易地重新創建功能分支:

$ git branch my_feature_branch <hash of commit Q> 

我不知道你是否意識到這一點,但理解這個關鍵是知道一個分支不比提交的「指針」或「書籤」多得多。

+0

不起作用。參考這個圖片:http://imgur.com/a/0DL9l - 合併base'my-feature-branch'有4fa54c2f300a6c7b0056568270c153b215d5b8d8 vs 46436103594f6bc35ce1106fc09fd702011b08ad'new-my-feature-branch',它是從提交ID創建的你建議。 – akirekadu

+0

@akirekadu那是因爲你在那裏重新創造了一種不同的情況。注意合併時的「快進」。最後你在'D'上有一個簡單的線性歷史'A-B-C-D',''master''和'C'上的'new_my_feature_branch'。 – mkrieger1

+0

要在快速轉發時創建真正的合併提交,可以使用'git merge --no-ff'。 – mkrieger1