我有如下存儲庫佈局: git
我想要實現的是從工做分支中挑選一系列提交併將其合併到集成分支中。 我對git至關陌生,我不知道如何準確地作到這一點(在一個操做中選擇合併範圍而不是合併中的提交範圍)而不弄亂存儲庫。 關於此有任何指示或想法嗎? 謝謝! bash
當涉及到一系列提交時,挑選櫻桃 是 是不實際的。 ide
就像Keith Kim在下面提到的那樣 ,Git 1.7.2+引入了對一系列提交進行櫻桃選擇的能力(可是您仍然須要意識到爲將來的合併選擇櫻桃的結果 ) svn
git cherry-pick」學會了選擇一系列提交
(例如「cherry-pick A..B
」和「cherry-pick --stdin
」),「git revert
」也是如此; 可是,它們不支持更好的排序控件「rebase [-i]
」。 佈局
在「
cherry-pick A..B
」格式中,A
應該早於B
若是它們的順序錯誤,則命令將靜默失敗 。 ui
若是要選擇範圍B
到D
(含) ,則爲B^..D
請參閱「 Git從先前提交的範圍建立分支? 」做爲插圖。 google
假設
B
不是根提交; 不然,您將收到「unknown revision
」錯誤。 code
注意:從Git 2.9.x / 2.10(2016年第三季度)開始,您能夠直接在孤兒分支(空頭)上挑選一系列提交:請參閱「 如何在git中使現有分支成爲孤兒 」。
原始答案(2010年1月)
進行rebase --onto
會更好,您能夠在集成分支的頂部重播給定的提交範圍,如Charles Bailey在此處所述 。
(另請在git rebase手冊頁中查找「這是將基於一個分支的主題分支移植到另外一個分支的方法,以查看git rebase --onto
的實際示例)」
若是您當前的分支是集成:
# Checkout a new temporary branch at the current location git checkout -b tmp # Move the integration branch to the head of the new patchset git branch -f integration last_SHA-1_of_working_branch_range # Rebase the patchset onto tmp, the old location of integration git rebase --onto tmp first_SHA-1_of_working_branch_range~1 integration
這將重播介於如下之間的全部內容:
first_SHA-1_of_working_branch_range
的父first_SHA-1_of_working_branch_range
(所以~1
):您要重播的第一個提交 integration
」(指向您要從working
分支重播的最後一個提交) 到「 tmp
」(指向integration
以前指向的位置)
若是重播其中一個提交時發生任何衝突,請執行如下操做:
git rebase --continue
」。 git rebase --skip
」 git rebase --abort
」取消全部操做(並將integration
分支放回tmp
分支) 從新rebase --onto
, integration
將返回到集成分支的最後一次提交(即「 tmp
」分支+全部重播的提交)
進行櫻桃挑選或rebase --onto
,請不要忘記它會對後續合併產生影響,如此處所述 。
這裏討論了一個純「 cherry-pick
」解決方案,其中涉及到如下內容:
若是您想使用補丁方法,則能夠選擇「 git format-patch | git am」和「 git cherry」。
當前,git cherry-pick
僅接受一次提交,可是若是您要選擇範圍B
到D
,則在git lingo中爲B^..D
,所以
git rev-list --reverse --topo-order B^..D | while read rev do git cherry-pick $rev || break done
可是不管如何,當您須要「重播」一系列提交時,單詞「 replay」應該促使您使用Git的「 rebase
」功能。
您肯定不想合併分支嗎? 若是工做分支中有一些您不須要的近期提交,則能夠只在須要的位置建立一個帶有HEAD的新分支。
如今,不管出於何種緣由,若是您確實確實想挑選一系列提交,一種簡便的方法是僅提取補丁集並將其應用於新的集成分支:
git format-patch A..B git checkout integration git am *.patch
不管如何,這本質上就是git-rebase所作的,可是不須要玩遊戲。 若是須要合併,能夠將--3way
添加到git-am
。 若是徹底按照說明進行操做,請確保執行此操做的目錄中沒有其餘* .patch文件...
我將VonC的代碼包裝到一個簡短的bash腳本git-multi-cherry-pick
,以便於運行:
#!/bin/bash if [ -z $1 ]; then echo "Equivalent to running git-cherry-pick on each of the commits in the range specified."; echo ""; echo "Usage: $0 start^..end"; echo ""; exit 1; fi git rev-list --reverse --topo-order $1 | while read rev do git cherry-pick $rev || break done
我目前正在使用它,由於我要重建一個項目的歷史記錄,該項目的第3方代碼和自定義項在同一svn幹線中混合在一塊兒。 我如今將核心第三方代碼,第三方模塊和自定義項拆分到本身的git分支中,以更好地瞭解之後的自定義項。 git-cherry-pick
在這種狀況下頗有用,由於我在同一存儲庫中有兩棵樹,但沒有共享祖先。
另外一個選擇多是與咱們的策略合併到該範圍以前的提交,而後與該範圍的最後一次提交(或分支到最後一個提交)進行「正常」合併。 所以,假設只有2345和3456的master提交要合併到功能分支中:
master: 1234 2345 3456 4567
在功能分支中:
git merge -s ours 4567 git merge 2345
從git v1.7.2開始,cherry pick能夠接受一系列提交:
git cherry-pick
學習了選擇一系列提交(例如cherry-pick A..B
和cherry-pick --stdin
cherry-pick A..B
),所以git revert
; 可是,它們不支持更好的序列控制庫rebase [-i]
。