如何挑选一系列提交并合并到另外一个分支?

我有如下存储库布局: 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]

相关文章
相关标签/搜索