关于git:如何将提交从一个分支复制到另一个分支?

How to copy commits from one branch to another?

我有两个师父的分支:

  • V2.1:(版本2)我已经工作了几个月了
  • WSS:我昨天创建的,目的是向我的主(在生产中)添加一个特定功能

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


使用

1
git cherry-pick <commit>

应用于您当前的分支机构。

我自己可能会交叉检查我在gitk中选择的提交,而cherry则通过右键单击提交条目来选择它们。

如果你想更自动地(带着所有的危险)并假设昨天在WSS上发生的所有提交,你可以使用jefromi建议的git logwith(--pretty)生成提交列表。

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

所以假设你使用bash,所有的东西都在一起。

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

如果这里出了什么问题(有很多潜在的问题),你就有麻烦了,因为这是在现场结账时进行的,所以要么手工挑选樱桃,要么像杰弗里米建议的那样使用钢筋网。


您真的应该有一个工作流,让您通过合并来完成这一切:

1
2
3
- 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

REBASE的一些方法可以帮助您:

如果您的历史记录如下:

1
2
3
- 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:

1
2
3
4
5
- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

那你就可以合并了!如果你真的,真的,真的不能达到你可以合并的程度,你仍然可以使用rebase一次有效地做几个樱桃选择:

1
2
3
4
5
# 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

注意:需要做一些额外的工作才能做到这一点的原因是,它正在您的存储库中创建重复的提交。这真的不是一件好事——简单的分支和合并的关键是能够通过将提交放在一个地方并将它们合并到需要的任何地方来完成所有事情。重复提交意味着一种永不合并这两个分支的意图(如果您决定以后要合并,就会发生冲突)。


git cherry-pick:应用一些现有承诺所带来的变化

假设我们有一个具有(x,y,z)提交的分支A。我们需要将这些承诺添加到B分支。我们将使用cherry-pick操作。

当我们使用cherry-pick时,应该按照与提交出现在分支A中相同的时间顺序在分支B上添加提交。

cherry pick确实支持一系列提交,但是如果您在该范围内合并了提交,那么它会变得非常复杂。

1
2
3
4
git checkout B
git cherry-pick SHA-COMMIT-X
git cherry-pick SHA-COMMIT-Y
git cherry-pick SHA-COMMIT-Z

工作流示例:

enter image description here

我们可以选择使用cherry-pick

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

-n或--no commit:通常命令会自动创建一个提交序列。此标志将对cherry pick每个命名的commit所必需的更改应用到工作树和索引,而不进行任何commit。此外,使用此选项时,索引不必与head commit匹配。根据索引的起始状态进行挑选。

这里有一篇关于cherry-pick的有趣文章。


您可以从要复制的提交中创建一个补丁,并将补丁应用到目标分支。


或者,如果你在福音传道者的立场上少了一点,你可以用一种我正在使用的丑陋的方式。在部署模板中,有一些提交我希望作为分支部署复制到我的主服务器上

1
2
3
git branch deploy deploy_template
git checkout deploy
git rebase master

这将在deploy_模板上创建新的分支deploy(我使用-f覆盖现有的deploy分支),然后将这个新分支重新设置为master,使deploy_模板保持不变。


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

1
2
git checkout v2.1
git merge <commit>