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

我从我的主人那里得到了两个分支:

  • v2.1:(版本2)我已经工作了几个月
  • wss:我昨天创建了一个特定的功能添加到我的主(在生产中)

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

986350 次浏览

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

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

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

所以你所要做的就是git checkout v2.1git merge wss。如果由于某种原因你真的不能这样做,并且你不能使用gitrebase将你的wss分支移动到正确的位置,那么从某个地方抓取单个提交并将其应用到其他地方的命令是git樱桃选择。只需签出要应用它的分支,然后运行git cherry-pick <SHA of commit to cherry-pick>

rebase的一些方法可能会拯救你:

如果你的历史看起来像这样:

- 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)

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

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

注意:执行此操作需要一些额外工作的原因是它在您的存储库中创建了重复提交。这不是一件好事-轻松分支和合并的全部意义在于能够通过将提交放在一个地方并将它们合并到需要的任何地方来完成所有事情。重复提交意味着永远不会合并这两个分支的意图(如果你稍后决定要合并,你会得到冲突)。

使用

git cherry-pick <commit>

<commit>应用于您的当前分支

我自己可能会交叉检查我在gitk中选择的提交,然后用右键单击那里的提交条目来选择它们。


如果你想更自动化(考虑到它的所有危险),假设昨天以来的所有提交都发生在wss上,你可以使用git log生成提交列表(Jefromi建议使用--pretty

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

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

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

如果这里出了问题(有很多潜在的),你就有麻烦了,因为这在实时结帐上有效,所以要么手动挑选,要么像Jefromi建议的那样使用rebase。

或者,如果你在布道者这边少一点,你可以用我使用的方式做一点丑陋的事情。在deploy_template有一些提交我想作为分支部署复制到我的主服务器上

git branch deploy deploy_templategit checkout deploygit rebase master

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

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

git checkout v2.1git merge <commit>

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

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

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

樱桃选择确实支持一系列提交,但如果您在该范围内进行合并提交,则会变得非常复杂

git checkout Bgit cherry-pick SHA-COMMIT-Xgit cherry-pick SHA-COMMIT-Ygit cherry-pick SHA-COMMIT-Z

工作流程示例:

在此处输入图片描述

我们可以使用cherry-pick选项

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

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

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

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

以下命令chry-picks提交由用户John撰写的存在于“开发”分支但不存在于“发布”分支中的提交,并按时间顺序执行。

git log develop --not release --format=%H --reverse --author John | git cherry-pick --stdin

假设我已经提交了对master分支的更改。我现在将获取提交的提交ID(xyz)。然后我必须去我需要推送我的提交的分支。

单个提交idxyz

git checkout branch-namegit cherry-pick xyzgit push origin branch-name

多个提交idxyzabcqwe

git checkout branch-namegit cherry-pick xyz abc qwegit push origin branch-name

这是另一种方法。

git checkout {SOURCE_BRANCH}               # switch to Source branch.git checkout {COMMIT_HASH}                 # go back to the desired commit.git checkout -b {temp_branch}              # create a new temporary branch from {COMMIT_HASH} snapshot.git checkout {TARGET_BRANCH}               # switch to Target branch.git merge {temp_branch}                    # merge code to your Target branch.git branch -d {temp_branch}                # delete the temp branch.

已经提到的答案涵盖了大部分内容,但似乎缺少的一件事是cherry-picking的--no-commit功能。

假设,你在功能分支上有多个提交,并且你想将所有提交“合并”到一个提交中并将它们放在你的主分支上。在这种情况下,你需要做的是:

git checkout <branch-on-which-to-add-features>git cherry-pick --no-commit <commit-hash>git cherry-pick --no-commit <commit-hash>...

最后,一旦你cherry-pick了所有必需的特性,你可以做一个最终的提交:

git commit -m "Some message for the merge commit"

理想情况下,如@陈志强所述,你应该使用mergerebase。但是如果你觉得没有其他选择,你可以使用cherry-picking。

使用内置的git gui进行樱桃挑选特定提交更安全:

对于ex:将一个提交从dev分支复制到main分支:

git checkout maingitk --all

然后右键单击所需的提交并选择Cherry-pick this commit

输入图片描述

gitk对于Mac:在Mac上安装gitk