[英]How can I retrospectively merge a git branch?
請注意 ,這不是為帶標志的重復-它變成了我不想 cherry-pick
,但merge
。 因此,我認為應該將其視為自己的問題,以防其他人遇到同樣的情況。
我有一個包含一系列提交的develop
分支。 當功能集完成時,我會定期將此分支合並為master
。 在過去的某個時刻,我意識到我應該合並develop
分支。 例如:
A
\ Merge
\ |
B--C--D--E--F
A
是master
上的最后一次提交, B
是develop
分支的第一次提交。
我希望將提交B
, C
和D
合並到master
,但我只知道如何合並整個分支。 最終,提交E
和F
將合並,但是現在我需要合並到D
A----------D
\ /
\ /
B--C--D--E--F
我知道我可以為一次提交執行以下操作,但是如何進行范圍操作?
$ git checkout master
$ git cherry-pick B
注意未來的自我 :記得始終創建一個功能分支!
首先,關於櫻桃挑選的快速評論:櫻桃挑選和合並是非常不同的(稍微更多)。
現在,合並。 通常我們會像這樣描述合並序列:
$ git checkout master
$ git merge sidebranch
如果自動合並順利,git將在當前分支上創建一個新的合並提交 - 在這種情況下,在master
- 每天“first”parent是當前分支的前一個tip,其第二個 parent是我們告訴的commit合並的git。
有第二個親本的事實是什么使這是一個合並提交。 以圖解方式得到:
A <----------- M <-- master
\ /
B <- C <- D <-- sidebranch
M
有兩個父母A
和D
名稱master
現在指向新的合並提交M
,而名稱sidebranch
不受影響,仍然指向D
git merge
與sidebranch
參數的作用是兩件事,其中只有一件非常重要:
merge branch sidebranch
或merge branch sidebranch into foo
,只有當前分支未命名為master
才會出現into foo
)。 第二項並不重要,至少不是git:git只顯示提交消息,它永遠不會依賴於消息。 如果您選擇編輯消息,則可以使其說出其他內容。
所有這一切的要點是你可以識別任何提交,而不僅僅是分支的提示,git可以合並它。 因此,如果sidebranch
繼續運行,就像你的情況一樣,但你具體指定了commit D
,你得到:
A <----------- M <-- master
\ /
B <- C <- D <- E <- F <-- sidebranch
這就是你想要的。 然而,Git的自動生成的合並提交消息文本表示merge commit <hash>
,這可能不是你想要的。 這很容易修復:只需編輯它以讀取merge branch sidebranch
。
(為了完成合並本身,git執行通常的三向合並 ,找到合並基礎並針對要合並的兩個提交區分該提交。)
merge和cherry-pick之間的主要區別不在於合並本身(你可以選擇一系列提交,甚至不通過在cherry-pick命令中添加-n
來提交每個提交:結果是什么git稱之為“squash merge”,除非效率低得多,你可能需要多次以這種方式解決相同的沖突)。 相反,它是最終提交不是合並提交 ,即沒有第二個父提交 。
這意味着生成的提交圖是不同的,即使源代碼更改是相同的(就像它們用於壓縮“合並”)。 這沒有立竿見影的效果,但這意味着未來的合並將不會知道櫻桃選擇已經發生,並且必須努力跳過它(這可能會也可能不會成功)。 記錄第二個父級為git提供了為后一次合並找到正確的新合並基礎所需的所有信息。
作為一個例子,考慮通過將B+C+D
的效果復制到master
上而獲得的“合並”:
A <-------- S <-- master
\
B <- C <- D <- E <- F <-- sidebranch
這里S
是通過“我們在B
做了什么”(通過差異A
對B
)並將其應用於A
的源樹,然后采用“我們在C
做了什么”(diff B
vs C
)並應用它來生成的,最后,采取“我們在D
做了什么”並應用它。 到目前為止一切都很好 - 我們在B
做的事情顯然必須干凈利落地應用於A
,依此類推。
當(或者可能“如果”)我們以后再次將sidebranch
合並到master
時會發生問題。 Git將搜索merge-base並發現它是commit A
,因此它將比較A
vs S
和A
vs F
然后它可以自動構建正確的樹,這取決於E
和F
的變化與我們之前采摘的變化。 如果我們已合並,git會將D
視為合並基礎,並比較D
-vs- F
以獲取新項目以進入master
。
試試這些命令。
git checkout master
git cherry-pick b^..d
Git 1.7.2引入了一系列提交的能力。
git cherry-pick“學會了選擇一系列提交(例如”cherry-pick A..B“和”cherry-pick --stdin“),”git revert“也是如此;這些不支持更好的排序控制”但是,rebase [-i]“有。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.