簡體   English   中英

我怎樣才能追溯合並git分支?

[英]How can I retrospectively merge a git branch?

請注意 ,這不是為帶標志的重復-它變成了我不想 cherry-pick ,但merge 因此,我認為應該將其視為自己的問題,以防其他人遇到同樣的情況。


我有一個包含一系列提交的develop分支。 當功能集完成時,我會定期將此分支合並為master 在過去的某個時刻,我意識到我應該合並develop分支。 例如:

A
 \     Merge
  \      |
   B--C--D--E--F

Amaster上的最后一次提交, Bdevelop分支的第一次提交。

我希望將提交BCD合並到master ,但我只知道如何合並整個分支。 最終,提交EF將合並,但是現在我需要合並到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有兩個父母AD 名稱master現在指向新的合並提交M ,而名稱sidebranch不受影響,仍然指向D

git mergesidebranch參數的作用是兩件事,其中只有一件非常重要:

  • 它將它轉換為特定的提交並使用該提交進行合並;
  • 它將參數名稱放入默認提交消息( merge branch sidebranchmerge 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做了什么”(通過差異AB )並將其應用於A的源樹,然后采用“我們在C做了什么”(diff B vs C )並應用它來生成的,最后,采取“我們在D做了什么”並應用它。 到目前為止一切都很好 - 我們在B做的事情顯然必須干凈利落地應用於A ,依此類推。

當(或者可能“如果”)我們以后再次將sidebranch合並到master時會發生問題。 Git將搜索merge-base並發現它是commit A ,因此它將比較A vs SA vs F 然后它可以自動構建正確的樹,這取決於EF的變化與我們之前采摘的變化。 如果我們已合並,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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM