08. rebase 不是 merge 的替代品:Git 故事线重构进阶
「Git」系列已发布: 00. 改崩代码不敢回退?Git 版本控制 3 分钟救你狗命 | 01. Git 装完不会配?Windows/macOS/Linux 三端配置一次到位 | 02. Git 配置总踩坑?全局/仓库/SSH 密钥一次搞懂 | 03. add/commit/push 别再死记:Git 工作流核心概念实操 | 04. Git 分支管理:5 步彻底搞懂 branch 与 merge | 05. clone/fetch/pull/push 分不清?Git 远程协作实战 | 06. 给版本打上永久印记:Git 标签管理与发布实战 | 07. 切分支怕丢改动?Git stash 暂存恢复保护现场 | 08. rebase 不是 merge 的替代品:Git 故事线重构进阶(本文) | 09. Git 日志与调试:log/blame/diff 让历史无所遁形
rebase 常被误用为 merge 的平替,其实它是“重构提交历史”的手术刀。本文讲清底层原理与适用边界,用对地方历史才干净。
分支管理(第 04 篇)和基础变基操作要很熟。下面涉及的交互式变基和历史重写都是破坏性操作,只在个人 feature 分支上练,千万别在共享分支上玩。
一、变基底层干了什么
搞清楚底层机制能避免大部分坑。git rebase分三步走:
- 找当前分支和目标分支的共同祖先。
- 把当前分支上每个提交的 diff 暂存起来。
- 切到目标分支最新提交,逐一 apply 这些 diff,生成全新提交。
变基前,feature 从 main 的 D 点分叉,拥有 A、B、C 三个提交:
gitGraph commit id: "D" branch feature commit id: "A" commit id: "B" commit id: "C" checkout main commit id: "E" commit id: "F" commit id: "G"
执行 git rebase main 分三步:① 找到共同祖先;② 暂存 A、B、C 的 diff;③ 在 G 上依次 apply,生成全新的 A’、B’、C’:
gitGraph commit id: "D" commit id: "E" commit id: "F" commit id: "G" branch feature commit id: "A'" commit id: "B'" commit id: "C'"
注意:A’、B’、C’ 是全新的提交,哈希和 A、B、C 完全不同。这就是为什么变基后本地和远程分支会分叉——历史已经被重写了。
1.1 交互式变基深入
1.1.1 合并提交(squash / fixup)
最实用的场景:把开发中零散的提交合并成清晰的逻辑单元。
# 变基最近 5 次提交
git rebase -i HEAD~5
编辑器里会看到:
a1b2c3d 初步实现登录功能
pick b2c3d4e 修复登录页面样式
pick d4e5f6g 修复校验逻辑 bug
pick e5f6g7h 添加单元测试
把要合并的改成
squash或fixup:
a1b2c3d 初步实现登录功能
squash b2c3d4e 修复登录页面样式
squash d4e5f6g 修复校验逻辑 bug
pick e5f6g7h 添加单元测试
结果:5 个提交 → 2 个提交(“实现登录功能” + “添加单元测试”)。squash和fixup的区别:squash允许你编辑合并后的提交信息,fixup直接把被合并提交的信息丢掉。
1.2 拆分提交(edit)
一个大提交拆成多个小的:
a1b2c3d 实现用户模块
edit b2c3d4e 实现订单模块
到
b2c3d4e时会暂停:
# 把提交回退到暂存区
git reset HEAD~1
# 分文件提交
git add src/order/create.py
git commit -m "实现订单创建功能"
git add src/order/list.py
git commit -m "实现订单列表功能"
# 继续
git rebase --continue
1.2.1 调顺序
在编辑器里直接拖动行就行:
# 原始顺序
pick a1b2c3d 添加单元测试
pick b2c3d4e 实现核心功能
# 调整为合理顺序(先功能、再测试、最后文档)
pick b2c3d4e 实现核心功能
pick a1b2c3d 添加单元测试
1.2.2 删提交(drop)
开发中不小心提交了调试代码或临时文件:
a1b2c3d 实现功能 A
drop b2c3d4e 临时调试代码——勿合并 # 直接删掉
1.3 变基冲突
# 变基时碰上冲突
git rebase main
# CONFLICT (content): Merge conflict in src/utils.py
# 解决后
git add src/utils.py
git rebase --continue
# 跳过当前提交(放弃它的修改)
git rebase --skip
# 完全放弃变基
git rebase --abort
变基冲突和
merge 冲突有一个关键区别:变基是逐提交应用的,同一个文件可能在不同提交里反复冲突。要有耐心,一次一次来。
1.4 高级变基
1.4.1 --onto:移植一段提交
把 feature 分支中某一段提交搬到 main 上:
git rebase --onto main E feature
场景:feature 从 develop 分叉,但想直接把 feature 中新增的提交变基到 main。
%% 变基前 gitGraph commit id: "A" commit id: "B" commit id: "C" commit id: "D" branch develop checkout develop commit id: "E" commit id: "F" commit id: "G" branch feature checkout feature commit id: "H" commit id: "I"
执行 git rebase --onto main G feature 后:
%% 变基后:feature 的 H、I 被重新落到 main 之上 gitGraph commit id: "A" commit id: "B" commit id: "C" commit id: "D" branch feature checkout feature commit id: "H'" commit id: "I'" checkout main merge feature branch develop checkout develop commit id: "E" commit id: "F" commit id: "G"
1.4.2 保留合并提交
默认git rebase会丢弃合并提交、把历史线性化。如果想保留某些合并提交:
git rebase --rebase-merges main
这在保留
CI 通过的合并提交(作为构建验证节点)时很有用。
1.5 autosquash
配合--fixup提交自动 squash:
# 先建 fixup 提交
git commit --fixup a1b2c3d -m "修复上次提交的小问题"
# 变基时自动应用
git rebase -i --autosquash HEAD~3
1.6 变基安全铁律
1.6.1 黄金法则
永远不要对已经推到公共仓库的提交变基。
怎么判断:
# 检查当前分支是否已推送
git status
# "Your branch is ahead of 'origin/feature' by 2 commits"
# 且确认远程没人基于你的分支工作 → 可以变基
#
# "Your branch and 'origin/main' have diverged"
# → 远程已有不同提交,变基会导致冲突和强制推送
# 看远程分支上多了哪些你本地没有的提交
git log origin/feature..feature
如果不小心对公共分支变基并
force push 了,通知所有团队成员执行:
git fetch origin
git rebase origin/main
# 或者更粗暴但更安全
git reset --hard origin/main
1.6.2 force-with-lease
# 别用这个
git push --force
# 用这个
git push --force-with-lease
# 更安全的:显式指定期望的远程状态
git push --force-with-lease=feature:origin/feature
1.7 文章引用
📌 本文首发于微信公众号 【运维知识点滴】——专注运维实战干货,微信搜索“运维知识点滴”或扫下方二维码关注,更新不迷路。
📎 微信原文:08. rebase 不是 merge 的替代品:Git 故事线重构进阶
| 微信公众号【运维知识点滴】 | 微信小程序【A5单据合并&大试卷拆分转A4打印】 |
|---|---|
![]() |
![]() |
| 运维实战干货 · 关注追更 | Word 转 PDF · 试卷/发票打印神器 · 免费 |
💡 小程序【A5单据合并&大试卷拆分转A4打印】是干嘛的? 一个 Word 转 PDF 的打印神器,专治“文档版式和打印机对不上”:
- A3 试卷打不出来? 学校发的电子版试卷多是 A3,家用打印机只吃 A4——上传 Word 一键转换:可缩到一页 A4(页数不变),也可对半拆成两张 A4(1:1 原大、字更清晰),两种模式自选;
- 版式不乱:真实渲染引擎原样转换、绝不重排内容,转出的 PDF 和原 Word 排版一致,公式/表格/图片不跑版;
- 两张 A5 单据拼一张 A4:出租车票、火车票等报销凭证拼版后,一次打印、整齐粘贴;
- 隐私省心:无需注册,转换结果留存 5 天、最多下载 5 次即自动删除,不留任何历史记录;
- 微信扫码即用,免费、免安装,支持 doc / docx(≤50MB)。
上一篇:07. 切分支怕丢改动?Git stash 暂存恢复保护现场 | 下一篇:09. Git 日志与调试:log/blame/diff 让历史无所遁形

