Git的文檔的muchderision主題...有很好的理由:
git的變基[-i | --interactive] [選項] [--exec <CMD>] [--onto <newbase>] [<上游> [<分支>]]
此處該參數被標記upstream
,和有幫助的( ?)從命令輸出參考git branch --set-upstream-to
和origin/<branch>
,這意味着您的本地分支必須有一個像origin/my-feature
這樣的遠程分支才能工作。但事實並非如此。
git rebase
做什麼是副本一系列提交,每個拷貝發生,如果你想在一個特定的運行git cherry-pick
提交。通過複製每提交一個線性提交圖中的提交,您將獲得複製開發分支的效果。 我認爲,這使得以圖表形式更有意義。例如,假設你有這樣的順序:
... <- o <- A <- B <-- master
\
C <- D <- E <-- my-feature
其中每個字母代表一些特定的承諾,其中一個大丑40個字符的SHA-1的數和提交歷史my-feature
與commit-連接起來master
的歷史記錄在提交o
。如果您在master
上創建了新分支my-feature
,然後又回到分支master
,進行了兩次提交,然後轉至my-feature
並進行了三次提交(每次提交的實際順序)無所謂:我只需要你在master
上做了兩個,現在我把他們作爲現在作爲第一個A
和第二個B
,並且在my-feature
上有三個。現在
,因爲它與發展情況,你可能會決定它將使基礎上,master
當前提示,即更有意義C
-through- E
,有C
的父提交是B
。
一個非常手動的方法來實現這一目標是:
$ git checkout master
$ git checkout -b new-my-feature
$ git cherry-pick <id of commit C>
$ git cherry-pick <id of commit D>
$ git cherry-pick <id of commit E>
這使得一個新的分支,new-my-feature
,並複製三個提交,這個結果:
C' - D' - E' <-- new-my-feature
/
... o - A - B <-- master
\
C - D - E <-- my-feature
的方式混帳構造新的提交C'
將比較樹 - 關聯的源快照 - 對於C
與其父提交o
的樹,將相同的更改應用於t ree for B
,然後重新使用提交消息C
進行新的提交。換句話說,提交C'
是C
的「副本」。 D'
與D
相同,E'
與E
相同。
在任何情況下,如果你把這個第三圖像,然後刪除my-feature
分支標籤,並重新命名new-my-feature
到my-feature
,你得到的是:
C' - D' - E' <-- my-feature
/
... o - A - B <-- master
原來的三所老my-feature
提交的「丟失「(他們通過」reflog「條目保存30天,但這些條目通常不可見,以免混淆視圖)。
git rebase
所做的是自動執行此過程:它找到要複製的提交序列,將序列複製到其他提交中,然後移動分支標籤。
你可以指定的是,所有沒有非常好記錄的選項都是分支名稱 - 默認爲當前分支 - 通常在某種程度上,間接地指向停止複製的點。 「目標」提交,重定位爲--onto <newbase>
,默認爲您給出的參數(如果有的話),請撥打<upstream>
。
這種工作方式依賴於理解其他相當重要的東西,這會影響雙點符號。
讓我們回到原來的圖形,我們再次做任何櫻桃採摘和分支標籤移動的,也就是說,之前我們變基之前有:
... - o - A - B <-- master
\
C - D - E <-- my-feature
現在讓我們來問git的是什麼版本在master..my-feature
:
$ git rev-list master..my-feature
e59f6c2d348d465e3147b11098126d3965686098
8413a79e67177d026d2d8e1ac66451b80bb25d62
1f9e0a53489aaca7859722e037a47e93858cbc42
(我做這些,但事實上這種設置,你會真正得到只有三個SHA-1)。
我認爲一個很好的方式來解釋這是在顏色填充/突出顯示(當然,我不能在這裏的文字做這個,所以你必須想像它)。
想象一下,您從my-feature
的提示開始,即提交E
。將此提交塗成綠色:這是「要使用」。然後,按照其父指針返回提交D
。將此提交也刷爲綠色。跟着那個到C
並且塗綠色;跟着那個到o
並且繪製那個綠色,然後繼續到整個圖形中的o
的父母。
然後,從master
的提示開始,即提交B
。將此提交塗成紅色:「停止」。然後,按照其父母提交A
,並將其塗成紅色。按照o
,用紅色油漆在綠色塗料上塗漆:「停止」。一路跟隨o
的父母,用紅漆覆蓋他們所有的綠色塗料。
(如果你願意,你可以做紅的第1,那麼綠,只要你不覆蓋任何紅配綠。)
結果,將提交該git rev-list
應該列出,正是那些(仍然)是綠色的提交,這只是我們想要改變的三個提交。即使我們從B
,master
的提示開始了「紅色列表」,情況也是如此。
所有這一切的簡短版本是,爲了重組,我們想要的 - 至少現在 - 是git rebase
將master
視爲「上游」。 rebase的「上游」參數提供了「紅色顏料」參數,master..my-feature
修訂說明符的左半部分和--onto
參數:我們想要複製提交,以便它們在master
的提示最後提交後出現。
實際上,您可以使用git branch --set-upstream-to
將master
(在您自己的私人存儲庫中)設置爲my-feature
的「上游」。上游不一定是像origin/branch
這樣的遠程跟蹤分支。您自己的本地分支機構在此處可以正常工(但是請記住,如果您開始共享此分支 - 將其推送到遠程git存儲庫(如origin
),那麼您可能希望在此時開始使用遠程跟蹤分支作爲「上游」,以提醒自己要分享,並獲得了較爲典型的變基流去。你可以做一個新的git branch --set-upstream-to
在任何時候改變「上游」。)
單詞「分支」的另一個git文檔問題的例子。它至少有兩種不同的含義。在作爲該腳註段落的一部分的圖表中,master
是一個「分支」(我喜歡稱其爲「分支標籤」或「分支名稱」)。同樣,my-feature
是一個分支。在這種情況下,這兩種標籤分別簡單地標註一個特定的提交 - B
和E
。但是,每個提交都有其自己的父提交指針:B
指向A
,E
指向D
,依此類推。遵循這些父指向箭頭產生的提交鏈也是一個「分支」。
在其確切點停止調用此類鏈「分支」取決於你的觀點:my-feature
可能會停止在提交o
,而master
可能會繼續回通過o
。 Git在這裏並沒有太多的幫助,儘管沒有總是正確的答案:它確實取決於你想包含的內容。
有做這一個稍微更簡單的方法,因爲不是一個承諾作爲參數git cherry-pick
可以採取更多:
$ git cherry-pick <id> <id> <id>
例如,或者:
$ git cherry-pick my-feature~3..my-feature
它使用在the gitrevisions documentation中描述的說明符可以讓git找到這三個ID。
像'HEAD〜1'(在最後一次提交之前提交)這樣的表達式也應該有效。如果有足夠的提交,它可能會更容易複製並粘貼來自日誌的散列,而不是計算您想要改變的提交數量。 – CoDEmanX