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

给你一囗甜甜゛ 提交于 2020-01-06 16:08:21

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

我有以下存储库布局:

  • 主分支(生产)
  • 积分
  • 工作中

我想要实现的是从工作分支中挑选一系列提交并将其合并到集成分支中。 我对git相当陌生,我不知道如何准确地做到这一点(在一个操作中选择合并范围而不是合并中的提交范围)而不弄乱存储库。 关于此有任何指示或想法吗? 谢谢!


#1楼

当涉及到一系列提交时,挑选樱桃 是 不实际的。

就像Keith Kim下面提到的那样 ,Git 1.7.2+引入了对一系列提交进行樱桃选择的能力(但是您仍然需要意识到为未来的合并选择樱桃结果

git cherry-pick”学会了选择一系列提交
(例如“ cherry-pick A..B ”和“ cherry-pick --stdin ”),“ git revert ”也是如此; 但是,它们不支持更好的排序控件“ rebase [-i] ”。

达米安 评论并警告我们:

在“ cherry-pick A..B ”格式中, A应该早于B
如果它们的顺序错误,则命令将静默失败

如果要选择范围BD (含) ,则为B^..D
请参阅“ Git从先前提交的范围创建分支? ”作为插图。

正如Jubobs 在评论中提到

假设B不是根提交; 否则,您将收到“ unknown revision ”错误。

注意:从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]

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!