如何合并Git分支,使主题提交变成孤儿提交?

3

我还在逐渐学习Git的一些更高级的功能...

鉴于以下的历史记录,我该如何清理主题分支的合并,以便它们出现在历史记录中作为一个提交?

[master] - - - - - - - C - - -
   \
   [feature] - A - - B - - D -

理想情况下,我希望在D处将[feature]与[master]合并,然后将[feature]合并到[master]中,使A和B变为孤立状态。
我原本以为可以简单地通过以下方式实现:
$ git rebase master # on feature branch
$ git co master
$ git merge --no-ff feature

然后使用以下方法清理孤立的提交:

$ git gc --prune=now --aggressive

这仍然会在历史记录中留下A和B - 我有遗漏什么吗?
4个回答

3
如果我重新绘制您的图表,将分支标记放置在分支末端(这反映了分支的实际表示),则您原来的情况是:
o --- C (master)
 \
   --- A --- B --- D (feature)

按照您所述,使用--no-ff进行变基和合并之后,现在您拥有:

o --- C ------------------ M (master)
 \      \                 /
  \       A' --- B' --- D' (feature)
   \
    --- A --- B --- D

根据我的理解,您现在想确保仓库中的ABD已被删除。首先,我强烈建议您不要担心这些提交记录。
但是,如果您真的想摆脱它们,那么您必须确保它们真正不可达,否则git gc --prune=now --aggressive将无法删除它们。就目前而言,它们仍然会被feature的reflog指向(至少是)。有多种方法可以从reflog中过期条目,例如:
git reflog expire --expire=now feature

...或者更安全的选择是设置配置变量gc.reflogexpireunreachablenow并使reflog过期:

git config gc.reflogexpireunreachable
git reflog expire feature

无论哪种情况,您都需要再次运行git gc --prune=now --aggressive
但是,重申我上面所说的话,我不会这样做 - 这些提交对任何人都没有伤害,而且使用git时reflog是一个有价值的安全网。

感谢您的建议和解释。 - bodacious

1
如果您想要“合并”A、B和D,可以使用交互式变基。
如果您的分支featuremaster之上(在此分支上发出git rebase master后),请执行以下操作:
git rebase -i master

然后,在将在编辑器中打开的文件中,将提交A和B上的pick替换为squash。Git将会将A和B压缩成D,并弹出一个编辑器以显示所有被压缩提交的提交消息。

1
如果您想将一个分支的效果合并为单个提交,则可以从主分支执行以下操作:
git merge --squash feature
git commit

尽管我个人认为在大多数情况下,保持分支上的各个提交不变是一个很好的功能。
或者,你可以在分支上使用`git rebase -i`命令,将所有的提交合并在一起,然后再将合并的结果与主分支(master)进行合并。

请删除您的一个答案,它们大部分相同! - Oleksandr Pryimak

0

为什么会移除 A 和 B?

git rebase master 会将 feature 分支移到 master 的顶端,当你提交时,feature 中的所有提交都会合并到 master。因此你将看到 A 和 B(实际上是 A' 和 B')。

git gc 与历史记录中所见的内容无关。它只会删除悬空提交(可能是 A 和 B,但现在在 master 中有 A' 和 B')。

如果你想将它们作为单个提交呈现,请尝试使用 --no-commit 选项或查看其他替代方案,如 git rebase -i(和压缩)。


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