将任何 Git 提交从一个分支移动到另一个分支

3

我有以下Git提交树:

R - A - B - C - D (master)

I would like:

R - A - B - D' (master)
        \ - C  (new-branch)

我该怎么做呢(假设这是可能的)?

我开始使用 git cherry-pick,但我没有成功将提交从主分支中删除。

谢谢。


1
你可能需要在cherry-pick之后跟着一个rebase -i来移除另一个提交,但我不建议完全删除它。 - Nic
2
在“after”图中,D是否代表与第一个D相同的更改集,还是代表与第一个D相同的树(文件)?看起来你的意图是仅保留更改集,因为你希望删除C所做的贡献。在这种情况下,惯例是称其为D'(D prime),以表示它不具有与原始D相同的数据(树/父项/提交信息)。 - tcovo
谢谢!我之前不知道这个惯例,但是我理解这种情况的模棱两可。 - Thomas
4个回答

3
直接在C处创建新分支,然后简单地将主分支(master)变基(rebase)以删除提交C,避免不必要的挑拣(cherry-picks):
在主分支(master)上:
git branch new-branch sha1-of-C
git rebase --onto sha1-of-C^ sha1-of-C master

第二个命令通过将“git-rebase”手册中的“分支”从“sha1-of-C”(“上游”)开始的master提交合并到sha1-of-C之前的提交来删除主分支中的C。
如果第二个命令太复杂,您也可以进行交互式变基: git rebase -i sha1-of-C^ 在交互式变基中,只需删除提交C,保存并退出即可。
在变基过程中,如果git报告合并冲突,请解决它们,使用git addgit rebase --continue。无论您选择哪种方法,都必须解决这些冲突。

3
您不能完全得到您想要的,因为提交记录会有所不同,但如果您执行以下操作,则文件内容将按照您的要求进行更改: $ git checkout master $ git reset --hard sha1-of-B # 将主分支设置回B $ git cherry-pick sha1-of-D # 将主分支设置为R-A-B-D' $ git checkout -b new-branch sha1-of-B # 将新分支设置为B $ git cherry-pick sha1-of-C # 将新分支设置为R-A-B-C'
请注意,在您检出新分支时,您不需要真正地挑选某个提交记录,您也可以轻松地执行以下操作: $ git reset sha1-of-C
这将实际上给您提供了R-A-B-C而不是R-A-B-C'。请注意,C和C'之间唯一的区别是提交时间。
一旦您进行重置,您可能很难找到各种提交记录的sha1哈希值(它们可以从reflog中获取),因此您可能需要在开始之前对所有内容进行标记,或将历史记录存储在某个地方。

非常感谢!它起了作用,尽管我在挑选D时不得不解决一些冲突。 - Thomas
正如Raman所指出的那样,让_new-branch_指向C的更快方法是在任何时候只需执行git branch new-branch sha1-of-C(此命令不关心HEAD是什么,即它不关心正在检出什么)。 - tcovo

1

在主分支上:

git branch new-branch
git reset --hard B
git cherry-pick D
git checkout new-branch
git reset --hard C

0
一个不涉及变量如BC的sha1的配方:

如果还没有检出,请执行git checkout master

git branch tempD              # create temporary branch, pointing to D
git branch new-branch HEAD^   # create new-branch, pointing to C
git reset --hard HEAD^^       # reset master to B
git cherry-pick tempD         # apply D's changeset onto B
git branch -D tempD           # remove temporary branch

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