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