最常用场景是将未推送的连续本地提交压缩为一条:执行git rebase -i head~3,首行pick、后两行改s或squash;若提交不连续则用git rebase -i ,注意父提交指目标第一条提交的前一个。

git rebase -i 合并连续提交最常用场景
想把最近 3 次本地提交压成 1 条,且没推送到远程——直接用 git rebase -i HEAD~3。它会拉出最近 3 条(从当前 HEAD 往前数,不含第 4 条),编辑器里第一行保持 pick,后面两行改成 squash 或 s。
常见错误:写成 HEAD~4 却只改了 2 行 squash,结果第 4 条被漏掉;或误把第一行也改成 squash,Git 会报错「no commit to squash into」。
-
HEAD~N的N是你要操作的总提交数,不是“要合并的条数” - 必须是连续提交,中间不能夹着别人推送的 commit
- 如果分支已推过远程,后续
git push必须加--force-with-lease,不能只用-f
用 commit ID 精确指定合并起点
当你不想数数字,或者提交不连续(比如中间有 merge、或你只想从某次 fix 开始合并),就用 git rebase -i <commit-id></commit-id>。这里的 <commit-id></commit-id> 是你**想保留的第一条提交的父提交**(即它前面那一个)。
例如目标提交是 abc1234,它的父提交是 def5678,那就运行 git rebase -i def5678。编辑器里出现的第一条就是 abc1234,后面你想合并的都标 squash。
- 用
git log --oneline -n 10快速查 ID,注意看父子关系 - 别复制错 commit ID —— 复制太短(如前 4 位)可能冲突,建议至少取前 7 位
- 如果选错起点,
rebase会把不该动的提交也拉进来,中途发现可立刻git rebase --abort
squash 和 fixup 的关键区别
两者都合并到前一条,但处理提交信息的方式完全不同:squash 会把所有被合并提交的 message 全塞进编辑器供你删改;fixup 则直接丢弃被合并提交的 message,只留第一个的原始内容。
适合用 fixup 的场景:你有一堆 fix: typo in README、chore: update .gitignore 这类临时补丁,不想在最终提交里留痕迹。
- 编辑器里写
f或fixup效果一样 - 如果用了
fixup,第二步编辑 commit message 的界面根本不会弹出来 -
fixup不保留Co-authored-by行,多人协作时慎用
push 前必须检查的三件事
rebase 完不等于结束。强制推送前漏掉任一条件,轻则同事 fetch 失败,重则丢失他人基于旧提交做的工作。
- 确认远程分支没人正在基于你即将覆盖的 commit 开发(查
git branch -r --contains <old-head></old-head>) - 确保本地分支和远程一致(
git fetch origin && git status显示 “Your branch is up to date”) - 用
git push origin <branch> --force-with-lease</branch>,而不是--force—— 前者会拒绝覆盖别人新推的提交
真正容易被忽略的是:rebase 后的 commit ID 全变了,所有基于旧 ID 的 git cherry-pick、git revert 都得重算。别等 Code Review 时才发现链接失效。











