在Git上将一组提交折叠成一个


70

我有进行大量小型提交的习惯,我对此表示满意。但是,我不时要使用一堆这些线性提交,并将它们折叠在一起,成为只有一次提交并能够编写新提交消息的功能。

我已经研究过文档,但对我来说似乎有点神秘。有人知道该怎么做吗?


1
看到这个问题与解答stackoverflow.com/questions/250238/...
iafonov

Git使得另一个简单的任务变得困难
甚至

Answers:


56

假设您要重写树的历史,直到(但不包括)commit为止a739b0d

export EDITOR=vim # or your favorite editor
git rebase a739b0d --interactive

请务必先阅读交互式基础知识


2
但是,假设我要“重新设置”的提交是过去的方式,在一堆合并和分支之前……这仍然有效吗?
rrb_bbr 2011年

1
是。在重新设置基准时,可以首先对提交进行重新排序,以便要压缩在一起的提交按照所有合并之后的顺序排列。然后,您可以将这些提交压缩到一个提交中。
yfeldblum 2011年

1
您的链接没有指向我的特定位置。git-scm.com/book/en/Git-Branching-Rebasing是重新设定页面;git-scm.com/book/en/Git-Tools-Rewriting-History具有更多概述。
Michael Scheper 2014年

重新设置基准是否还会节省磁盘空间?
CMCDragonkai 2015年

@CMCDragonkai不,之前和之后的提交都存储在您的reflog中。
2015年

66

假设您不关心保留任何现有的提交消息,那么可以使用一个漂亮(且快速)的git配方。首先,确保您的分支已签出:

git checkout <branch-to-squash>

为了安全起见,让我们标记当前提交。

git tag my-branch-backup

接下来,将分支HEAD返回到您的最后一次提交(无需修改工作空间或索引)。编辑:最后一次好的提交是您要保留的分支上的最新提交。

git reset --soft <last-good-commit>

使用git status,您会注意到功能分支上的所有更改现在都已上演。剩下要做的就是...

git commit

此方法非常适合合并冗长而复杂的git历史记录和粗糙合并。另外,没有合并/变基冲突可以解决!

现在,如果您需要保留任何现有的提交消息或做任何比上述允许的事情,都可以使用 git rebase --interactive

解决方案源自:http : //makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit

参考: http //git-scm.com/docs/git-reset

参考:http : //git-scm.com/docs/git-rebase


6
这是一个很好的答案-如果有310次提交来压缩,似乎每个提交都引入了重新设置错误。使用您的方法快速,轻松而正确。
tbm

7
@MarceloMason好问题。请将“最后一次良好提交”解释为“您要保留的分支上的最新提交”。例如,如果您要压缩主题分支的历史记录一直到它与master分支的分歧,最后一个好的提交将是merge-basemaster和您的topic分支的。如果分支上有十个提交,而只想合并前五个,则最后一个好的提交将是HEAD~5
Ben Amos

有用的技术,但我建议以下几点:确保从您的硬件备份了存储库(例如,在Github上),并从“分支到压榨”创建了一个全新的分支进行工作。当我这样做时,发现的问题更少了。
布伦丹

3
使用此方法的另一件可爱的事是,如果您不需要更改集的一部分,则可以轻松地对其进行重置。通过预先进行在新分支上执行壁球也很容易git checkout -b my_squashed_branch
约翰

4
完成折叠提交后,可以使用将更改推送到远程git push -f
哈桑

15

使用命令git rebase -i <commit>where<commit>是最后一次稳定提交的SHA。

这将带您进入编辑器,在这里您可以替换pick每个提交旁边的标签,因为<commit>您已将其作为交互式rebase命令的参数包含在内。在要开始折叠的命令上,将其替换pickreword,对于此后要折叠到其中的每个提交,将其替换pickfixup。保存,然后将允许您提供新的提交消息。


6

您可以使用以下方法将任意数量的提交压缩为一个提交

git rebase --interactive <commit>

3
重要的是要考虑您已经或某些协作者将其推送到Github中的存储库中的情况。见stackoverflow.com/questions/5667884/...
e3matheus

这是有道理的,但由于-i与相同--interactive,唯一的区别是push
Matt Ball

嗯是的 但是我评论说,这只是为了澄清一下,如果您在重新设置基准之前已经被迫掌握,那么必须通过--force来完成,对吧?而且,如果您的另一个协作者进行了推送,则根本不应该进行基准调整。
e3matheus 2011年

那就是为什么您在一个单独的分支上进行重新基准并将您的重新基准合并到主数据库中的原因
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.