合并(清理)提交历史
下面是一个 git log 示例,一共有两个分支:main 和 squash-multi-commit。
其中 squash-multi-commit 是基于 main 分支(794d76af444cbadd7b5e553a4d3aadf2512bafd6)叉出来,之后又推送了 4 个 commit:
我觉得 squash-multi-commit 分支的 commit message 写的是一塌糊涂,不够清晰。为了让 commit 信息更友好,我现在想重新修正(合并/清理)这些提交历史(比如将某些琐碎的提交“压缩/合并”成 1 个提交),该怎么解决呢?这里就需要用到 git rebase -i 了。
从基准分支开始修正提交历史
以上面的 log 为例,当前分支只有一个基准分支: main(commit=794d76af444cbadd7b5e553a4d3aadf2512bafd6)。
如果我想从该基准分支开始修正提交历史,就可以使用下面命令:
git rebase -i main
因为当前分支只有 4 次提交记录,所以实际会修正 4 次提交历史。
修正最近 N 次提交历史
另一种是修正最近 N 次提交,这种方式就比较友好,适合少量 commit 的合并操作。以 log 为例,该新分支只有 4 次提交,我想要修正最近 4 次提交:
git rebase -i HEAD~4
因为新分支只有 4 次提交,所以 -i HEAD~4 和 -i main 是等效的。
实操
现在开始实践,我需要将第一次提交合并给第二次,将第三次提交合并给第四次:
执行 rebase 命令,之后会进入一个编辑窗口,只需要将第二次、第四次提交的 pick 修改为 squash 即可:
squash 解释
squash 的作用将前一次 pick 或 squash 合并过来。比如有如下几个 commit:
pick commit_1
pick commit_2
pick commit_3
pick commit_4
pick commit_5
如果我修改为:
pick commit_1
pick commit_2
squash commit_3
squash commit_4
pick commit_5
就表示将 commit_2 合并给 commit_3,commit_3 继续合并给 commit_4。
保存并关闭编辑器。Git 会再次弹出一个编辑器,让你为前一步合并的操作创建新的提交信息。因为做了两次合并,所以会依次弹出两次,下面是第一次合并弹窗:
重写第一次合并的 commit message,之后保存即可。
接着会进入第二次合并弹窗,一样重写 commit message:
保存之后再看一下 log:
这样就实现了 commit 合并/清理,之后需要强制推送到远程:
git push origin squash-multi-commit --force-with-lease
# 或(不推荐)
git push origin squash-multi-commit --force
合并任意 commit
前面已经做 squash 的作用做了说明:squash 会将前面的 pick 和 squash 全部合并过来。并不是说只能按照顺序合并,所以你可以修正 git log 中的任意部分 commit,比如修正前三次合并,保留最后一次合并:

保存之后重写 commit message:

再看下 git log:

最后执行强制提交即可:
git push origin squash-multi-commit --force-with-lease
现在就可以放飞自我了,随意写一下 commit 即可,反正之后能重新修正~
JetBrains IDE
如果直接使用图形化 IDE,操作起来就简单很多。以 RustRover 为例,只需要按顺序选中要合并的 commit,右键菜单选择 Squash Commits... 即可:
在弹窗中重写 commit message:
看下 log:
最后执行下强制推送就好了