从Git中的单个分支中删除提交记录

28
我有两个分支,master和feature1。我在feature1上工作时发现需要处理其他不相关的事情。不幸的是,我忘记从主分支上创建分支,而是从feature1创建了我的feature2分支。现在我想把feature2合并到master中,但由于该分支中有feature1的部分内容,所以无法进行合并。
我该如何从feature2分支中删除feature1的提交记录?这需要使用rebase吗?
我感觉如果我能够将feature2的起始参考点更改为master所在位置,那可能会有所帮助,但我不知道如何操作。
编辑:
感谢您们的回答!我尝试了@Mark解决方案中的rebase操作,但意识到历史记录比我最初想象的要复杂得多。 feature 2已经合并到其他feature分支中,而且master曾经被合并到feature2中。此外,master上还有与feature2无关的其他提交。所有内容仍然只在本地。
实际上,我的历史记录更像是这样的:
A - B - C - D - - - - - - - - - - - - - L - M  master  
            |                          
            |               - I - J - K  feature2                  
            \              /           \
             - E - F - G - H - - - - - -N - O - P  feature1

我所想要的是这个:

A - B - C - D - - - - - - - - - -  L - M  master
            |\                          
            |  - - - - - I - J - K  feature2                  
            \                     \
              - E - F - G - H - - - N - O - P  feature1

我也尝试过:

git rebase --onto 1524b824cfce5856a49e feature1 feature2
// 1524b824cfce5856a49e == D

但这只是将分支名称feature 2指向了1524,并使提交I、J、K保留其原始父级。


如果您正在使用共享存储库,请小心。如果您尝试更改的提交已经被“推送”到其他人拉取的位置,那么当您在提交历史记录中进行操作时,将会遇到问题。如果您正在使用类似GitHub的工具,则不允许更改提交历史记录。 - Dave Lancea
谢谢警告!幸运的是,一切还在本地。 - Andrew
所以你想要将 ID 分支出来,然后在 D 后的提交中合并回 master?除非我漏掉了什么,否则这没有太多意义。 - Andy
不,那是我的失误 :) 实际上,我想要将 K 合并回主分支。 - Andrew
1
所以基本上你想做的就是从_feature2_中删除E-F-G-H? - Andy
1
是的,我想要保持这两个特性的历史记录分开,因为feature2已准备好合并到主干中,但feature1还没有。 - Andrew
2个回答

29

如果只有你在进行feature2分支的工作,并且没有与其他人共享该分支,那么在合并之前重新设置基础分支是可行的。例如,您可以执行以下操作:

git checkout feature2
git rebase --onto master feature1 feature2

使用以下命令将你的feature2分支重写,使其由自从从feature1分支创建后在feature2分支上进行的所有提交所组成,并重新应用到master上。建议你之后使用gitk --all或类似的git历史查看器来检查该操作的结果是否符合您的预期。

顺便提一下,这正是用来解释--onto的场景,在git rebase文档中有说明,请参见以以下段落开始的部分:

以下是如何将基于一个分支的主题分支移植到另一个分支上,以假装您从后者分支派生了主题分支,使用rebase --onto。 [...]


根据问题附带的更多材料更新:

从以下历史记录开始,它看起来像这样:

A - B - C - D - - - - - - - - - - - - - L - M  master  
            |                          
            |               - I - J - K  feature2                  
            \              /           \
             - E - F - G - H - - - - - -N - O - P  feature1

通过以下步骤,您可以得到您想要的内容:

git checkout feature2
git rebase --onto D H feature2
这将使你拥有以下外观的历史记录:
A - B - C - D - - - - - - - - - - - - - - - - - - - L - M  master  
            |\
            | \ - I' J' K' feature2       I - J - K                    
            \                           /           \
             - - - - - - - E - F - G - H - - - - - -N - O - P  feature1

在创建您想要的 feature1 合并之前,您应该记录下 OP 的 SHA1sum。 (我假设 N 只是一个普通的合并,而不是“恶意合并”。)

然后进行硬重置,将 feature1 移回到 H

git checkout feature1
git rest --hard H

那么你应该有历史记录:

A - B - C - D - - - - - - - - - - - - - - - - - - - L - M  master  
            |\
            | \ - I' J' K' feature2
            \
             - - - - - - - E - F - G - H feature1

现在你显然想要将K'合并到feature1中:

git merge K'

A - B - C - D - - - - - - - - - - - - - - - - - - - L - M  master  
            |\
            | \ - I' - J' - - - - - - - K' feature2
            \                             \
             - - - - - - - E - F - G - H - Z feature1

最后,您可以使用以下命令将旧的 OP 提取到 feature1 中:

git cherry-pick O
git cherry-pick P

离开的方法:

A - B - C - D - - - - - - - - - - - - - - - - - - - L - M  master  
            |\
            | \ - I' - J' - - - - - - - K' feature2
            \                            \
             - - - - - - - E - F - G - H - Z - - O' - P' feature1

谢谢您的回复!我进行了编辑以添加更多细节。 - Andrew
我查看了我的历史记录,发现我的图表是错误的(现已更新)。feature2没有合并到主分支中,feature1也没有。 - Andrew
如果有人在这里尝试帮助你,那么正确地发布信息非常重要,否则你只是浪费他们的时间。你的问题已经经历了两次修订,完全改变了它的意思,因此需要的答案也随之改变。无论如何,我已经更新了我的答案以匹配你的第三个版本... - Mark Longair
在玩弄这个东西这么长时间后,我认为我同意了!但是,你的答案对于理解我如何修复这个问题非常有帮助。实际的拓扑比我在这里描述的要复杂得多。 - Andrew
rebase --onto master feature1 feature2 正是我一直在寻找的。非常感谢。Git 真是太棒了! - phatmann
显示剩余2条评论

2
如果您不介意将feature2合并回到P而不是M,这里有一个相对简单的解决方案。
  1. 将I-J-K变基到D上,查看“更有趣的变基”部分的标题
  2. 将O-P变基到H上。方法与步骤1相同。
  3. 最后,使用git merge feature2feature2合并到feature1中,同时检出feature1
如果您想将K合并到特定提交中,则变基会稍微复杂一些。

1
你能给我一个示例,说明如何将feature1进行变基以删除挑选的提交吗? - Andrew
这里有一个 Stack Overflow 的问题回答了如何做到这一点。 - Andy
我最初的想法是错误的,feature1和feature2都没有合并到主分支master中。所以这应该会更容易一些。 - Andrew
根据您的澄清,再更新一次并提供另一种解决方案。 - Andy

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