用 Rebase 把功能分支线性合并回 main
在个人项目或小团队中,先把功能分支 rebase 到最新 main,再以 fast-forward 方式线性合并回 main。
[!info] related notes
- 前置笔记: git, Git 中的 merge 和 rebase, Git 中的 fast-forward merge
- 相关 MOC: Git MOC
- 相关流程: Git 协作流程
用 Rebase 把功能分支线性合并回 main
目标
在功能分支和 main 都已经继续前进时,先把功能分支的提交 rebase 到最新 main 之上,再以 fast-forward 方式合并回 main,让历史保持线性。
适用场景
- 个人项目,或只有少量协作者的小团队
- 希望
main历史尽量线性、易读 - 功能分支只由你自己维护,没有多人共享
如果你想先理解为什么这里可以“快进合并”,先看 Git 中的 fast-forward merge。
前置条件
- 当前工作区是干净的,或你已经把未提交修改先提交 /
stash - 你明确知道
rebase会重写功能分支上的 commit hash - 该功能分支不是多人共享分支
步骤
1. 确认当前状态
先确认你在功能分支上,并且看清双方各自独有的提交。
git branch --show-current
git log --oneline main..HEAD
git log --oneline HEAD..main
如果你看到功能分支和 main 都各自有新提交,说明它们已经分叉(diverged)。
2. 拉取最新的 main
git fetch origin main
这一步只更新本地对 origin/main 的引用,不会改动你当前分支的工作树。
3. 把功能分支 rebase 到最新 main 之上
git rebase origin/main
这会把你当前功能分支上的提交重新应用到最新的 origin/main 之后。
如果有冲突:
git add <resolved-file>
git rebase --continue
如果想放弃这次 rebase:
git rebase --abort
4. 切到 main 并做 fast-forward 合并
先把本地 main 对齐到远程的最新状态:
git checkout main
git pull --ff-only origin main
然后合并功能分支:
git merge --ff-only <feature-branch>
这里显式使用 --ff-only,是为了保证“只能快进,不能偷偷退化成普通 merge”。如果前面的 rebase 已经完成,而且 main 在此期间没有新增提交,这里通常会 fast-forward,不会产生新的 merge commit。
5. 推送并清理分支
git push origin main
git branch -d <feature-branch>
git push origin --delete <feature-branch>
本地删除分支时优先用 -d。只有在 Git 因历史重写而拒绝删除、且你确认分支已不再需要时,才改用 -D。
为什么这一步能 fast-forward
在 git rebase origin/main 之前,功能分支和 main 可能是分叉状态;rebase 之后,功能分支的提交会被重新放到最新 main 之后。
这意味着在第 4 步执行合并时,main 通常已经成为功能分支的祖先,因此 Git 只需要前移 main 指针,而不需要再创建新的 merge commit。
如果想看完整原理和 --ff-only / --no-ff 的区别,直接看 Git 中的 fast-forward merge。
历史对比
使用普通 merge 时
* Merge branch 'feature/xxx' into main
|\
| * feat commit 2
| * feat commit 1
|/
* main commit C
* main commit B
* commit A
使用 rebase + fast-forward merge 时
* feat commit 2
* feat commit 1
* main commit C
* main commit B
* commit A
线性历史更适合回看“功能是在什么基础上进入主线的”。
验证
git log --oneline --graph main -n 10中看不到额外的 merge commitgit status显示工作区干净- 远程
main已包含你的功能提交 - 本地和远程功能分支都已按需要清理
常见问题
为什么不直接在 main 上 merge 功能分支
如果你的目标是保留线性历史,而功能分支又是单人维护,那么先 rebase 再 fast-forward 更容易阅读历史。
为什么多人共享分支时要慎用 rebase
因为 rebase 会重写 commit hash。别人如果已经基于旧历史继续工作,再同步时会遇到额外的冲突和历史整理成本。
本地 main 为什么建议 git pull --ff-only origin main
因为这里的目标是“确认本地 main 已经和远程对齐”,而不是在你不知情时顺手再制造一个 merge commit。