如何将提交从一个分支复制到另一个分支?


727

我的主人有两个分支:

  • v2.1:(版本2)我已经研究了几个月
  • wss:我昨天创建的,旨在向我的母版添加一个特定功能(正在生产中)

有没有办法将昨天的提交内容从wss复制到v2.1?


简单地将提交(或一系列提交)从一个分支复制到另一个分支,此答案对我有最大的帮助:stackoverflow.com/questions/1994463/…–
caramba

Answers:


563

您实际上应该有一个工作流,可以通过合并来完成全部工作:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (wss)

因此,您要做的就是git checkout v2.1git merge wss。如果由于某种原因您确实无法执行此操作,并且无法使用git rebase将wss分支移至正确的位置,则从某个地方获取单个提交并将其应用于其他地方的命令是git cherry-pick。只需签出要应用它的分支,然后运行git cherry-pick <SHA of commit to cherry-pick>

重新设置基准的某些方法可以为您节省:

如果您的历史记录如下所示:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

您可以使用git rebase --onto v2 v2-only wss将wss直接移动到v2:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

然后,您可以合并!如果你真的,真的,真的不能去的地步,你可以合并,你仍然可以使用底垫中来一次切实做好几个樱桃挑选:

# wss-starting-point is the SHA1/branch immediately before the first commit to rebase
git branch wss-to-rebase wss
git rebase --onto v2.1 wss-starting-point wss-to-rebase
git checkout v2.1
git merge wss-to-rebase

注意:之所以需要做一些额外的工作,是因为它正在您的存储库中创建重复的提交。这确实不是一件好事-轻松进行分支和合并的全部目的是能够通过将提交放在一个地方并将其合并到需要的地方来完成所有工作。重复提交意味着永远不要合并这两个分支(如果您决定以后再合并,则会产生冲突)。


1
无法完全同意这个答案。+1。另见我老的答案说明了樱桃采摘的后果:stackoverflow.com/questions/881092/...
VonC

18
关于如何正确执行此操作的绝佳答案!我希望我也可以两次投票赞成创建ASCII图的工作。
gotgenes 2010年

@VonC:感谢您的支持,以及有关为什么不选择的更多信息-我知道我在那儿漏了一点。@gotgenes:谢谢!我认为这完全值得付出努力-仅查看git-rebase手册页。没有更好的方法来解释它。
卡斯卡贝尔

至于为什么您可能无法合并-Git合并与git-svn配合不好。要将一系列提交从一个SVN分支复制到另一个,我最终选择了它们,然后执行了交互式的rebase / reword来删除错误的git-svn-id引用,然后dcommit再次执行。尽管我本可以省去挑剔的步骤,而仅使用一个变基。
鲍勃

1
这是我的用例:严重的错误修复已提交给功能分支。我需要它掌握才能立即投入生产。这将节省我的屁股。
Captain Hypertext

910

采用

git cherry-pick <commit>

申请<commit>当前的分行

我本人可能会交叉检查我选择的提交,gitk然后右键单击那里的提交条目来挑选它们。


如果您想更加自动化(有所有危险)并假设自昨天以来所有提交都发生在wss上,则可以使用生成提交列表git log--pretty由Jefromi建议)

git log --reverse --since=yesterday --pretty=%H

所以一切都假设您使用 bash

for commit in $(git log --reverse --since=yesterday --pretty=%H);
do
    git cherry-pick $commit
done

如果这里出了问题(很有可能),则您会遇到麻烦,因为这可以在实时结帐中进行,因此可以手动执行樱桃小贴士或使用Jefromi建议的rebase。


--pretty选项的所有占位符都在git-log联机帮助页中。您可以获取所需的任何格式-对于以易于解析的形式获取脚本所需的字段特别有用。
卡斯卡贝尔

我还要指出的是,假设您确实想创建重复的提交,则git rebase在我的答案中使用的方法会更可靠。特别是,使用这样的for循环,如果其中一个樱桃小问题失败了,它仍然会尝试完成所有其他问题。可以说,这是非常非常不好的。
卡斯卡贝尔

2
同意 这就是为什么我从不使用它,而是手动进行操作的原因。但是,至少对于问题标题,“挑剔”仍然是答案。我修改了回复。
本杰明·班尼尔

1
有人提交了一个旧的/不正确的分支,并且让我选择将该提交放入正确的分支中(同时仍将其保留为提交者)。完善。
Patrick

8
难得一见的git答案是简单直接的解决方案,而不是通过git的复杂性来蜿蜒来证明答题者对它的了解程度。
Przemek D'

74

git cherry-pick :应用一些现有提交所引入的更改

假设我们有分支(A)的提交(X,Y,Z)。我们需要将这些提交加入到分支。我们将使用这些cherry-pick操作。

当我们使用cherry-pick,我们应该分支中加入提交在同一时间顺序将提交出现在分公司一个

cherry-pick确实支持一定范围的提交,但是如果您在该范围内进行合并提交,它将变得非常复杂

git checkout B
git cherry-pick SHA-COMMIT-X
git cherry-pick SHA-COMMIT-Y
git cherry-pick SHA-COMMIT-Z

工作流程示例:

在此处输入图片说明

我们可以使用cherry-pick选择

-e或--edit:使用此选项,git cherry-pick将允许您在提交之前编辑提交消息。

-n或--no-commit:通常,该命令会自动创建一系列提交。此标志将必要的更改应用到选择每个命名提交的工作树和索引中,而不进行任何提交。另外,使用此选项时,索引不必与HEAD提交匹配。对索引的开始状态进行挑选。

这里有一个有趣的文章有关cherry-pick



12

或者,如果您在传教士方面比较少,您可以做一些我使用的丑陋方法。在deploy_template中,有一些我想在分支主机上复制的提交

git branch deploy deploy_template
git checkout deploy
git rebase master

这将在deploy_template上创建新的分支部署(我使用-f覆盖现有的deploy分支),然后将此新分支重新建立到master上,而保持deploy_template不变。


1

对于仅将分支wss的最后一个提交复制到v2.1的简单情况,您只需获取提交ID(git log --oneline | head -n 1)并执行以下操作:

git checkout v2.1
git merge <commit>

这需要签出到另一个分支。
CoolMind

1

cherry-pick命令可以从标准输入中读取提交列表。

以下命令cherry-picks提交由用户John创作的,存在于“ develop”分支中但不存在于“ release”分支中的命令,并按时间顺序执行。

git log develop --not release --format=%H --reverse --author John | git cherry-pick --stdin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.