如何挑選一系列提交併合併到另外一個分支?

我有如下存儲庫佈局: git

  • 主分支(生產)
  • 積分
  • 工做中

我想要實現的是從工做分支中挑選一系列提交併將其合併到集成分支中。 我對git至關陌生,我不知道如何準確地作到這一點(在一個操做中選擇合併範圍而不是合併中的提交範圍)而不弄亂存儲庫。 關於此有任何指示或想法嗎? 謝謝! bash


#1樓

當涉及到一系列提交時,挑選櫻桃 是 不實際的。 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

若是要選擇範圍BD (含) ,則爲B^..D
請參閱「 Git從先前提交的範圍建立分支? 」做爲插圖。 google

正如Jubobs 在評論中提到spa

假設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 --ontointegration將返回到集成分支的最後一次提交(即「 tmp 」分支+全部重播的提交)

進行櫻桃挑選或rebase --onto ,請不要忘記它會對後續合併產生影響,如此處所述


這裏討論了一個純「 cherry-pick 」解決方案,其中涉及到如下內容:

若是您想使用補丁方法,則能夠選擇「 git format-patch | git am」和「 git cherry」。
當前, git cherry-pick僅接受一次提交,可是若是您要選擇範圍BD ,則在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 」功能。


#2樓

您肯定不想合併分支嗎? 若是工做分支中有一些您不須要的近期提交,則能夠只在須要的位置建立一個帶有HEAD的新分支。

如今,不管出於何種緣由,若是您確實確實想挑選一系列提交,一種簡便的方法是僅提取補丁集並將其應用於新的集成分支:

git format-patch A..B
git checkout integration
git am *.patch

不管如何,這本質上就是git-rebase所作的,可是不須要玩遊戲。 若是須要合併,能夠將--3way添加到git-am 。 若是徹底按照說明進行操做,請確保執行此操做的目錄中沒有其餘* .patch文件...


#3樓

我將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在這種狀況下頗有用,由於我在同一存儲庫中有兩棵樹,但沒有共享祖先。


#4樓

另外一個選擇多是與咱們的策略合併到該範圍以前的提交,而後與該範圍的最後一次提交(或分支到最後一個提交)進行「正常」合併。 所以,假設只有2345和3456的master提交要合併到功能分支中:

master:
1234
2345
3456
4567

在功能分支中:

git merge -s ours 4567
git merge 2345

#5樓

從git v1.7.2開始,cherry pick能夠接受一系列提交:

git cherry-pick學習了選擇一系列提交(例如cherry-pick A..Bcherry-pick --stdin cherry-pick A..B ),所以git revert ; 可是,它們不支持更好的序列控制庫rebase [-i]

相關文章
相關標籤/搜索