是否可能将一系列提交回溯地变成一个分支?

55

假设我有一个git仓库,在主分支上进行了工作,我能否事后创建一个分支。例如:

A - B - C - A1 - D - A2 - E

我想让它看起来像这样:

A - A1 - A2   
\           \   
B - C - D - E

具体使用场景是当我将一堆提交挑选到旧版本分支中,需要将其合并到多个更旧版本中,而我不想在所有这些版本上重复挑选提交。

本质上,这本应该作为特性或主题分支的好处,但没有像那样创建。

5个回答

124

如果你想要在一个分支中使所有的提交都是在版本XXX之后发生的,我认为这比其他提议的方法容易得多。

$ git branch fixes       # copies master to new branch
$ git reset --hard XXX   # resets master to XXX

这些提交现在仅存在于“fixes”分支中。

Git的帮助页面reset章节描述了将提交撤销并变成一个主题分支的过程。


1
很高兴我一直读到最后一个答案!- 至少对于我的特定用例来说,这是迄今为止最简单的解决方案 - Brian Leathem
3
我本周已经第二次回到这个答案。我希望我能再给@alltom一个赞! - Brian Leathem
10
对于该_XXX_的一个有用值只需使用origin/master:假设你在master分支上,接受所有未推送的提交并将它们视为一个分支。最后你也可能想要运行git checkout fixes命令来实际切换到你的新分支。 - Jesse Glick
@JesseGlick的情况是一个值得了解的有用特例。 - Roly
如何在这之后进行推送?git push -f origin master被拒绝。 - Dims
@Dims 那就可以了。听起来你的远程已禁用强制推送,因此您将无法从远程分支中删除提交。 - alltom

25

当然可以。(使用Git几乎没有什么做不到的事情。:)

git checkout -b new-branch hash-of-A
git cherry-pick hash-of-A1
git cherry-pick hash-of-A2

这将创建一个新的分支,从提交A开始。然后你再次回到相同的提交,创建另一个分支:

git checkout -b new-branch2 hash-of-A
git cherry-pick hash-of-B
git cherry-pick hash-of-C
git cherry-pick hash-of-D
git cherry-pick hash-of-E
git merge new-branch
现在你只需合并 new-branchnew-branch2 即可获得所需的结构并删除旧分支。
当然,Dustin 说的仍然有效:提交的哈希值将会改变,因此只有在未发布更改时才应执行此操作。

所以如果我所在的分支是主分支,我应该将主分支的名称移动到新分支2的头部?没错。谢谢。 - Otto
1
是的,自那时起,我的交互式变基技能有了很大提高。 :) - Bombe

5

由于哈希值将会发生变化,因此您无法透明地执行此操作。但是,您只需要分支HEAD并在两个分支上使用rebase -i命令来删除相应的更改即可。


0
忘掉所有的挑选。只需两次交互式变基,省略更改,每次创建一个新分支,然后合并这两个分支即可。

0
你想要做的是实际上“重写”历史。提交的标识符将会改变,在某些情况下,提交所给出的更改集也会改变。因此,如果有人可能基于您想要更改的旧版本分支上的工作,最好不要这样做。但是,如果您没有发布此分支,请随意操作。
让我们假设我们想要更改的分支名为“master”,我们想要开始新分支的点名为“A”(在给定示例中,您可以使用的名称之一是“master〜6”)。
首先,让我们从提交“A”创建一个新分支,命名为“fixes”。
$ git checkout -b fixes A

这也会使分支“fixes”变为当前分支。因为我们只想要取消樱桃拣选的几个提交,所以我们可以在“fixes”分支上进行樱桃拣选:

$ git cherry-pick A1
$ git cherry-pick A2

然后我们想要从分支'master'中删除提交'A1'和'A2'。由于我们只想要删除一些提交,可能还有很多我们想要保留的提交,所以我们会使用'git rebase --interactive'来完成这个操作:
$ git rebase -i fixes master

在提交“ A”(即分支“ master”和分支“ fixes”的合并基础)后,将启动一个编辑器,并显示所有“ master”中的提交。 列表如下:

pick deadbee B
pick fa1afe1 C
pick a98d4ba A1
...

删除包含提交 'A1' 和 'A2' 的行,保存更改,关闭编辑器(或以其他方式将更改发送到交互式变基),Git 将重新应用除您已删除的提交之外的所有提交。

然后您可以完成以下操作:

$ git merge fixes

(git-rebase 把我们留在了重写后的分支 'master' 上)。


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