使用Git rebase来压缩旧提交

时间:2015-03-23 02:23:08

标签: git

假设我的git历史记录如下:

-- A -- B -- C -- D -- 
    \            /
     -----E----- 

是否有一种相对快速的方法将B和C压缩成一次提交?

我希望我的最终历史看起来像:

-- A -- BC' -- D' --
    \         /
     ----E----

使用vanilla rebasing很容易压缩B和C - 它似乎是让新的Commit取代B和C成为麻烦的祖先或者D。

有一个分支指向D签出,并运行git rebase -i master(前身为A),并选择压缩C,我的结果历史记录如下:

A -- BC' -- E'
 \
  --- E

2 个答案:

答案 0 :(得分:1)

假设此图表示您的主分支:

master: A <- B <- C <- D (what you have)
master: A <- S <- D      (what you want)

您可以在交互模式下使用git rebase -irebase。您将看到如下所示的提交列表:

git checkout master
git rebase -i master

pick 0vmw31r comment for commit D
pick dnmwe91 comment for commit C
squash 209vmiq comment for commit B
pick d89gmlk comment for commit A

完成后,键入以下内容以完成rebase:

git rebase --continue

通过为提交B选择squash,它会将提交B组合到提交C中,从而为您提供所需的内容。请注意,压缩BC提交可能会导致合并冲突。

  

使用vanilla rebasing很容易压缩B和C - 似乎是新的Commit取代B和C成为麻烦的祖先或者D。

不仅容易让新的Commit取代B和C成为D的祖先,这是默认行为。

答案 1 :(得分:0)

我不确定这是 im 可能使用git rebase“开箱即用”(使用--preserve),但它很容易 1 git filter-branch相关,通过过滤使您完全删除提交B。然后,过滤器序列会将C的树复制到C',并使C'的父级为A,并将D的树复制到{ {1}}并让D'的父母(仍有两个人)分别为D'E

请注意,虽然我在这里调用副本C',但它有C的树, 包含C'中已更改的内容。所以你可以恰当地称它为B而你得到的就是你画的。

BC'

(在这里填写B的ID,并使用相应的positive-ref;使用branchname~5..branchname或类似的方法来减少迭代次数的提交,选择足够高的git filter-branch --commit-filter ' if [ "$GIT_COMMIT" = id-of-B ]; then skip_commit "$@"; else git commit-tree "$@"; fi' branchname 值来制作filter-branch看看需要什么,但又足够低,不要“复制”毕竟不会改变的提交。

您也可以使用较低级别的git命令(具体来说,两个~命令,然后是强制分支移动)来执行此操作。在下面的脚注1中,这可能会变得更容易(取决于git commit-tree是否是有问题的分支的最尖端提交,以及D的舒适度。


1 因为任何filter-branch都可以说是“容易”... :-)即使你彻底理解了它,仍然有后过滤清洁 - 也可以。