如何在Git中将“分裂”的合并历史线性化?

3

很明显,但我找不到方法。每个手册都描述了在现有分支的顶部重新安置或简单的交互式重新安置等方法。假设我有一个类似于钻石形状的git历史记录,如下:

*   949430f Merge commit (D) (HEAD, mybranch)
|\  
| * e6a2e8b (C)
* | 3e653ff (B)
|/  
*   9c3641f Base commit (A)

我希望您能够记录历史,例如:

我想要实现以下历史记录:

*   949430f Combined commit (BCD)
|  
*   9c3641f Base commit (A)

提交 B 和 C 可能会被合并或丢弃,都无所谓,我只想保留结果。而且我不想因为解决冲突而回滚提交。

以下是我尝试过的方法:

1)简单地压缩 B 和 C 是无法实现的。

git rebase -i HEAD~2
...
p 3e653ff (B)
f e6a2e8b (C)
...
Could not apply a91f3a4

好的,这有些可以理解,存在一些冲突。

2) 我无法通过压缩来实现那个目标。

git rebase -i -p HEAD~3
...
pick 9c3641f Base commit (A)
f 3e653ff (B)
f e6a2e8b (C)
pick 949430f Merge commit (D)
...
error: unable to match a91f3a4...

3) 我甚至无法放弃B和C。

git rebase -i -p -m HEAD~3
...
pick 9c3641f Base commit (A)
#pick 3e653ff (B)
#pick e6a2e8b (C)
pick 949430f Merge commit (D)
...
error: Commit 949430f is merged but option -m is not set.
fatal: cherry-pick failed
Could not pick 4f3e6231b5cecf57434613ca3afd2a21ba375eb9

为什么?这里有选项“-m”...

有谁知道如何解决这个问题吗?

3个回答

6

2
完整的答案是 git reset --soft commitA; git add .; git commit -m "Combined commit" - aragaer
1
你不需要 git add:软重置会保留索引不变。(我假设你在分支的顶端,在提交 D 上。请记住,Git 存储文件而不是增量;如果你在提交 D 上并将其放入索引中,则这些是最新的文件。) - torek
那就更好了 8) - aragaer
@aragaer:虽然我要指出的是,一般来说 git add . 也不会有什么问题(除非有一些杂乱无章的文件被添加进来,但是假设你在这个时候已经设置好了 .gitignore 文件...)。 - torek
我有一种冲动,想在开头添加 git clean -qdf - aragaer
哇,谢谢你们,这真的很简单。我想我被整个“重写历史”的事情误导了。 - ScalewingedAcidicorn

1

我建议先将提交图线性化,然后再将它们压缩在一起:

$ git checkout commitA -b newbranch
$ git cherry-pick commitB
$ git cherry-pick commitC
[resolve any conflicts]
$ git rebase -i commitA
[change the command for commitC to 'squash']

谢谢,那是一个解决方案,但我将不得不再次解决冲突。 - ScalewingedAcidicorn

1
git rebase -i 9c3641f^ # 1 before base commit

然后在交互式编辑器中

pick 9c3641f Base commit (A)
pick 3e653ff (B)
fixup e6a2e8b (C)
fixup 949430f Merge commit (D) (HEAD, mybranch)

我实际上期望最后一个不出现,因为在我的经验中,在交互式变基期间合并提交会消失。

这将把B和C压缩成一个提交。D将消失,而且你也不想要它,因为它没有添加代码。

这将给您所需的输出。你忽略的概念是需要保留第一个提交(pick),但如果你“fixup”其他两个,则它们将合并到其中。你需要给它们一个不是基础提交的东西来合并。因此,你选择第二个,然后第三个合并到它上面,给你两个提交。

你也可以这样做

git rebase -i 9c3641f

然后在交互式编辑器中就看不到基础提交,但是剩余行的 "pick" 和 "fixup" 将相同。

我已经尝试过了。Git拒绝将B和C压缩成一个提交。但无论如何,还是谢谢你。 - ScalewingedAcidicorn
我经常这样做。你能澄清一下“refuses to squish” 是什么意思吗?是指冲突还是其他情况?如果需要,可以在 Twitter 上联系我,我们可以解决问题(特别是如果有公共分支可供调试)。 - masukomi

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