- 已经会 merge / pull 的开发者
- 想整理本地提交历史的人
Command Reference
git rebase 教程
解释 git rebase 的核心模型、推荐流程、风险边界和恢复办法。
- 知道共享历史和本地历史的区别
- 愿意先看 reflog 再做改写
- 对已共享提交做 rebase
- 冲突时不先保住旧位置就继续重试
一句话理解
git rebase 会把一组提交重新应用到新的基底之上,所以你通常会得到“内容相近但提交 ID 变化过”的历史。
把 rebase 想成“把你这条分支上的提交重新排队,再接到新的基底后面”。它不是简单合并,而是重写提交之间的祖先关系。
把它想成“把自己的提交重新排队”。图里最重要的不是字母本身,而是 E/F 变成了 E'/F' 这件事,这正是为什么 rebase 会被视为改写历史。
什么时候应该用
- 让特性分支追上最新的
main - 合并前整理提交历史
- 使用交互式 rebase 调整提交顺序、压缩提交、修改提交信息
什么时候不要轻易用
- 公共分支已经被其他人基于其继续开发时
- 你不清楚团队对共享历史是否允许改写时
- 你还没有准备好恢复方案时
实践上,rebase 最适合“自己的特性分支”。
只要这段历史已经进入 review、CI 或同事的工作流,rebase 的问题就不再只是“会不会冲突”,而是“会不会让别人依赖的提交位置整体变化”。
基本流程
场景:让特性分支同步最新主分支
git checkout feature/login
git fetch origin
git rebase origin/main
建议按这个顺序做的原因:
- 先切到目标分支
- 先 fetch,确保你看到的是远端最新状态
- 再明确指定新的基底
冲突时怎么处理
当 rebase 过程中发生冲突时,一般按下面的节奏处理:
git status
# 手动解决冲突
git add <resolved-files>
git rebase --continue
如果你决定放弃这次 rebase:
git rebase --abort
一个更稳的实际工作流
如果你准备在本地整理自己的特性分支,比较稳的顺序通常是:
git status,确认工作区干净git fetch origin- 如担心风险,先建一个备份分支
- 再执行
git rebase origin/main - 最后用
git log --oneline --graph快速复核历史
备份分支很简单:
git branch backup/feature-login-before-rebase
这一步在高风险场景下非常值,因为它把“能回去”先做实了。
在高风险 rebase 前先建 backup/... 分支,成本很低,但会显著降低你后面做判断时的心理压力。
交互式 rebase 最常见的用途
git rebase -i HEAD~4
它常用于:
- 压缩零碎提交
- 让提交顺序更符合阅读逻辑
- 修改提交信息
- 删除不该保留的实验性提交
交互式 rebase 里最常见的动作
虽然 rebase -i 可以做很多事,但最常见的其实就这几类:
pick:保留提交reword:修改提交信息squash:把小提交压进前一个提交fixup:类似 squash,但丢弃当前提交说明drop:删除不想保留的提交
一个安全的团队建议
如果你的分支已经推送到远端,但仍想整理历史,优先遵守这条规则:
- 只 rebase 自己负责的分支
- 推送时使用
git push --force-with-lease
--force-with-lease 比裸 --force 更安全,因为它会先检查远端引用是否已经被别人更新。
pull --rebase 和手动 rebase 的区别
很多人会问:既然可以 git pull --rebase,为什么还推荐先 fetch 再手动 rebase?
原因是手动流程更清楚:
- 你先看到远端状态
- 再自己决定要不要改写本地历史
- 出问题时也更容易判断是哪一步出了问题
看图判断什么时候适合 rebase
如果你看到的关系更像“我自己的分支落后了主分支,但这些提交还没共享出去”,那就很适合用上面的 rebase 模式。
如果你脑中更接近“这条分支已经被 review、CI 或同事一起使用”,那就要先把注意力从“历史能不能变漂亮”切回“历史能不能安全改写”。
常见误区
误区 1:rebase 和 merge 只是长得不一样
不完全对。它们都会整合代码,但对历史的表达方式不同。rebase 会改写提交基底,因此历史更线性,但也更容易在共享分支上制造混乱。
误区 2:rebase 出错就完了
通常没有。只要对象还在,reflog 往往可以帮你回到 rebase 前的状态。
误区 3:pull 默认就是我想要的 rebase
不是。git pull 是否使用 rebase,取决于配置或命令行参数。
误区 4:只要是自己的分支就一定可以放心 rebase
也不绝对。如果这个分支已经被 CI、review 流程或同事依赖,改写历史仍然会带来协调成本。
推荐的恢复思路
如果你在 rebase 后发现历史不对,第一反应不是慌,而是:
git reflog
找到 rebase 前的 HEAD,再决定是否:
git reset --hard <safe-commit>
如果你不确定该不该直接 reset,更保守的做法是:
git checkout -b rescue/rebase HEAD@{1}
先把 rebase 前位置接住,再决定后续怎么处理。
哪些场景最适合 rebase
- 本地特性分支落后于主分支
- 发起 PR 前整理提交
- 你希望把“修修补补的小提交”压成更清晰的逻辑块
哪些场景更适合 merge
- 这段历史已经共享给多人
- 团队更重视保留真实分叉过程
- 你不想承担 force push 带来的沟通成本
教学补充建议
后续可以继续补充以下分支专题:
--onto的可视化解释- 交互式 rebase 的指令清单
- rebase 与 merge 的对照案例
- 共享分支历史改写的团队规范
这条命令在流程里解决什么问题
git rebase 直接影响历史表达、引用位置或提交之间的关系。读这类命令时,要先判断这次操作是在整理本地未共享历史,还是在处理已经公开给团队的历史。
典型用例
- 在合并、回滚、挑提交或整理提交序列时,用
git rebase重塑历史表达。 - 把
git rebase放进“先备份、再变更、最后复核”的高风险操作流程,降低误操作损失。 - 在复盘冲突、回滚事故或判断分支关系时,用
git rebase理清提交之间的因果链。
图例理解
特殊情况与边界
- 历史类命令最常见的风险,是对已经共享出去的提交继续做重写或移动。
- 如果这次操作可能影响团队协作,先跑
git status、git log --oneline --graph和git reflog,再决定是否继续。 - 一旦不确定,就先建一个备份分支,让自己保留“能回去”的选项。
- 如果分支已经进入评审、CI 或被他人基于其继续开发,就要先判断这次改写历史是否还安全。
跟着做一遍
先在临时仓库或实验分支里做,目标不是记命令,而是观察“提交 ID 变化了,但改动内容还在”这件事。
git switch -c lab/rebase-demo # 做两次提交 # 然后切回 main 再做一次提交跟着做
- 切回 feature 分支并执行 `git fetch`。
- 运行 `git rebase origin/main` 或对本地 main 做 rebase。
- 再执行 `git log --oneline --graph --decorate -6` 对照图形。
- 你的 feature 提交会重新接到新的 main 后面。
- 旧提交 ID 会变成新的提交 ID。
- 如果没有冲突,工作内容通常还在,但历史表达变了。
- 如果这条分支已经被同事基于其继续开发,就不该直接 rebase 后强推。
- 如果 rebase 一半发现不对,不要继续乱试,先用 `git rebase --abort` 或 `git reflog` 找回原位置。
- 如果你只是想把别人改动合进来而不改写自己的共享历史,merge 往往更合适。