如何在git中将特定提交移动到另一个分支的基础上?

442

情况如下:

  • 主分支(master)在X处
  • 快速修补分支1(quickfix1)在X+2个提交处

具体为:

o-o-X (master HEAD)
     \
      q1a--q1b (quickfix1 HEAD)

然后我开始着手处理 quickfix2 的问题,但是由于过失,我选择了 quickfix1 作为源分支进行复制,而不是 master。现在,quickfix2 包含 X + 2 次提交以及 2 个相关提交。

o-o-X (master HEAD)
     \
      q1a--q1b (quickfix1 HEAD)
              \
               q2a--q2b (quickfix2 HEAD)

现在我想创建一个带有quickfix2的分支,但是不包括属于quickfix1的两个提交。

      q2a'--q2b' (quickfix2 HEAD)
     /
o-o-X (master HEAD)
     \ 
      q1a--q1b (quickfix1 HEAD)
我尝试从quickfix2的某个版本创建补丁,但该补丁不会保留提交历史记录。有没有一种方法可以保存我的提交历史记录,但是在quickfix1中没有更改的分支?

可能是使用Git将最近的提交移动到新分支的重复问题。 - Kevin
14
这个问题只是询问如何将提交记录从一个分支移动到另一个分支,而这个问题则有一个额外的要求,即不包括quickfix1分支上的提交记录(请注意答案的差异)。 - Scott Weldon
5个回答

417

这是一个经典的 rebase --onto 的例子:

 # let's go to current master (X, where quickfix2 should begin)
 git checkout master

 # replay every commit *after* quickfix1 up to quickfix2 HEAD.
 git rebase --onto master quickfix1 quickfix2 

所以你应该从以下步骤开始:

o-o-X (master HEAD)
     \ 
      q1a--q1b (quickfix1 HEAD)
              \
               q2a--q2b (quickfix2 HEAD)

发送给:

      q2a'--q2b' (new quickfix2 HEAD)
     /
o-o-X (master HEAD)
     \ 
      q1a--q1b (quickfix1 HEAD)

最好在干净的工作目录上完成此操作。
请查看git config --global rebase.autostash true,特别是在Git 2.10之后


29
请注意,这些步骤将修改 quickfix2 的历史记录,因此如果您已经共享了该分支,请改用 Cherry-pick(请参见以下答案)。 - Max Chernyak
1
仅供记录:使用SmartGit的日志,只需将q2a拖到X上,并从出现的对话框选项中选择Rebase 2 commits - Thomas S.
1
@ThomasS。有趣。这是一个不错的GUI实现git rebase --onto - VonC
1
我必须承认,我经常做一些傻事,比如提交到错误的分支,SmartGit日志视图GUI在同样的情况下已经多次拯救了我。 - WORMSS
1
@Cosine 同意。我已经编辑了我的答案,添加了对 rebase.autostash 配置的引用:这将在进行变基时避免工作树中正在进行的任何工作丢失。 - VonC
显示剩余2条评论

178

您可以使用git cherry-pick命令来选择您想要复制的提交。

最好的方法可能是从主分支创建分支,然后在该分支上使用git cherry-pick命令选取快速修复2中您需要的两个提交。


1
这也是如果您想移动一个提交的最佳选择。谢谢。 - Alex from Jitbit

170

你可以做的最简单的事情是挑选一个区间。它与rebase --onto做的一样,但更容易让人理解 :)

git cherry-pick quickfix1..quickfix2

6
据我所知,使用git merge合并分支时不会丢失原始提交记录,因此对于像我这样的“小心谨慎者”似乎更可取;但是rebase --onto命令是否也能保留原始更改呢? - akavel
6
rebasecherry-pick都会给你新的SHA密钥。这是因为每个提交都是存储库的独特快照。 - Christoph
6
@akavel的意思是cherry-pick会保留原有分支中的提交记录,这是正确的。 - Mr_and_Mrs_D
4
不管价值如何,我试图像这个答案一样挑选一个范围,并且它混淆了我的存储库。我不得不为每个提交单独进行“cherry-pick”操作。(也许不用说,但如果有人遇到麻烦,需要按照提交的时间顺序进行“cherry-pick”)。 - carmenism
3
git checkout 在这里非常关键。你的 HEAD 是什么? - Sławomir Lenart

35

我认为它是:

git checkout master
git checkout -b good_quickfix2
git cherry-pick quickfix2^
git cherry-pick quickfix2

3
"cherry-pick" 命令使用提交哈希值,如果您只想从某个地方获取提交并将其放到另一个地方,这是一种可行的方法。请确保首先执行正确分支的 checkout <branch> 命令。 - John Leidegren

-2
// on your branch that holds the commit you want to pass
$ git log
// copy the commit hash found
$ git checkout [branch that will copy the commit]
$ git reset --hard [hash of the commit you want to copy from the other branch]
// remove the [brackets]

其他更有用的命令和解释在这里:Git指南


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接