用 Rebase 把功能分支线性合并回 main

在个人项目或小团队中,先把功能分支 rebase 到最新 main,再以 fast-forward 方式线性合并回 main。

#type / howto #status / evergreen #tech / ops #resource / git

[!info] related notes

用 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 commit
  • git status 显示工作区干净
  • 远程 main 已包含你的功能提交
  • 本地和远程功能分支都已按需要清理

常见问题

为什么不直接在 main 上 merge 功能分支

如果你的目标是保留线性历史,而功能分支又是单人维护,那么先 rebase 再 fast-forward 更容易阅读历史。

为什么多人共享分支时要慎用 rebase

因为 rebase 会重写 commit hash。别人如果已经基于旧历史继续工作,再同步时会遇到额外的冲突和历史整理成本。

本地 main 为什么建议 git pull --ff-only origin main

因为这里的目标是“确认本地 main 已经和远程对齐”,而不是在你不知情时顺手再制造一个 merge commit。

创建于 2026/4/30 更新于 2026/5/27