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

时间:2015-06-29 16:48:51

标签: git rebase

一定非常明显,但我发现无法做到这一点。每个手册都将变基描述为现有分支或简单交互式变基的顶部,这就是全部。假设,我有一个类似钻石形状的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 个答案:

答案 0 :(得分:6)

您想要的是git reset --soft(加a commit as noted by aragaer)。尽管问题的情况不同,请参阅this answer by VonC

答案 1 :(得分: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']

答案 2 :(得分: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)

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

这会将B和C压缩成一个提交。 D会消失,你不会真的想要它,因为它不会添加代码。

这将为您提供所需的输出。你错过的概念性事情是你需要保留第一个提交(选择),但如果你“修复”其他两个,它们将合并到它。你需要给它们一些东西来合并到那个不是基础的提交。所以你选择第二个,然后第三个合并到它给你两个提交。

您也可以

git rebase -i 9c3641f

然后只是在交互式编辑器中看不到基本提交,但其余行的pickfixup将是相同的。