如何在 Git 中线性化"splintered"合并历史记录?



这一定很明显,但我找不到任何方法。每本手册都描述了在现有分支的顶部或简单的交互式重基,仅此而已。假设,我有一个类似于这样的菱形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"。。。

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

您想要的是git reset --soft(加上aragaer指出的提交)。尽管问题中的情况不同,请参阅VonC的回答。

我会先尝试将提交图线性化,然后将它们压缩在一起:

$ 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']
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),但如果你"修复"了其他两个,它们就会合并到其中。你需要给它们一些可以合并的东西,而不是基本提交。因此,您选择第二个,然后第三个合并到其中,从而提供两个提交。

你也可以做

git rebase -i 9c3641f

然后在交互式编辑器中看不到基本提交,但CCD_ 2和CCD_。

最新更新