git rebase vs merge 深度对比:何时用哪个 / 团队协作规范

一、为什么 90% 团队 rebase vs merge 用错

去年帮一个30 人研发团队排查”为什么 git log 没法看”,打开仓库一看:feature 分支 merge 完 main 之后又 merge一次最新 main,然后又有同事 rebase 一次,导致同一个 feature commit 在历史里出现 3 个不同 hash。同事查问题时 git bisect 直接断裂。

这不是个例。我观察过 50+ 团队的 Git 使用,90% 在 rebase 和 merge 之间摇摆:要么一刀切全用 merge,历史像圣诞树;要么一刀切全用 rebase,团队协作天天打架。本质是没搞懂两者的底层差异。

二、底层原理:merge vs rebase

merge 是三方合并:把两个分支的最新 commit 和它们的最近公共祖先一起做 diff,生成一个新的 commit指向两个父节点。保留完整分支脉络。

rebase 是重放 commit:把当前分支从”分叉点”之后的所有 commit摘下来,在目标分支最新 commit 之上重新应用一遍。生成全新的 commit(hash 不同)。

1
2
3
4
5
6
7
8
9
10
11
merge 后:
A---B---C (main)
\
D---E---M (feature)

merge commit

rebase 后:
A---B---C---D'---E' (feature)

新的 commit hash

三、3 个真实场景对比图

场景 1:本地 feature 同步 main 最新代码

1
2
3
4
5
6
7
初始:main: A-B-Cfeature: A-B-D-Emerge main 后:
main: A-B-C
feature: A-B-D-E-M(多了 merge commit,历史分叉)

rebase main 后:
feature: A-B-C-D'-E'
(线性历史,但 D E 变成 D' E'hash 变了)

场景 2:发版分支 hotfix 同步

1
2
3
4
5
release: A-B-C-D-E-Xhotfix
main: A-B-C-D-E-Y(其他功能)

合并 hotfixmain
推荐 merge --no-ff:保留 hotfix 分支信息

场景 3:发版 tag

tag 永远从 merge commit 切,不要从 rebase 后的 commit 切,否则回溯时找不到 hotfix 上下文。

五、黄金规则:永远不要 rebase 已推送的共享分支

这是 Git 社区的硬规则:

  • ✅ 可以 rebase:本地 feature 分支、还没推送的 commit、自己的分支
  • ❌ 不要 rebase:已经 push 到 origin 的 main / develop / release 分支、别人正在用的分支

为什么?rebase 会重写 commit hash,你强制 push 后,同事的本地分支就指向了”消失的 commit”,出现诡异冲突。补救办法是 git reflog 找回旧 hash,但代价大。

六、实战 1:本地 feature 分支 rebase main

典型工作流——feature 分支开发两周,main 已经领先 50 个 commit,PR 合并前先 rebase 解决冲突:

1
2
3
4
5
6
7
8
9
10
11
12
# 1. 当前在 feature 分支,先 fetch 最新 main
git fetch origin
git checkout feature/login# 2. rebase 到 origin/maingit rebase origin/main
# 如果冲突:
# - 解决冲突文件
# - git add <文件>
# - git rebase --continue
# - 重复直到完成

# 3. 强制 push 到自己的远程分支
git push --force-with-lease origin feature/login
# --force-with-lease 比 --force 安全:如果同事刚 push 过新 commit,会拒绝覆盖

--force-with-lease 是 Git 2.30+ 的安全网:会检查远程分支是否被别人推进过,避免误覆盖同事的提交。

七、实战 2:merge –no-ff 保留分支信息

如果你想保留”这个 feature 包含哪些 commit”,用 --no-ff

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 默认 merge --no-ff 创建 merge commit
git checkout main
git merge --no-ff feature/login
# 输出提示输入 merge commit message```

效果:main 历史里能看到 "Merge branch 'feature/login'" 这个 commit,点击进去能看完整的 feature commit 列表。对运维、回溯、二次回滚都很有用。

## 八、实战 3:interactive rebase 整理提交

开发过程中 commit 可能很乱:"fix typo""WIP""fix bug again",合并前用 interactive rebase 整理:

```bash
# 整理最近 5 个 commit
git rebase -i HEAD~5

# 打开编辑器,类似:
# pick a1b2c3 feat: 添加登录接口
# pick d4e5f6 fix typo
# pick g7h8i9 WIP
# pick j1k2l3 fix bug again
# pick m4n5o6 完成单元测试

# 改成(squash / reword / drop):
# pick a1b2c3 feat: 添加登录接口
# s d4e5f6 fix typo ← squash合并到上一个# drop g7h8i9 WIP ← 删除# r j1k2l3 fix bug again ← reword 修改 commit message
# s m4n5o6 完成单元测试 ← squash

保存退出后,Git 会按你的指令重放、整理 commit。整理完 PR 看起来干净多了。

九、3 种团队规范对比

GitFlow(2010 年 Vincent Driessen 提出):

1
2
3
4
5
master (main) ————————————————tag v1.0———————tag v2.0 \              / \ /
develop ————————————————————————————————
\ / \ /
feature/login release/v1.1 /
hotfix/xxx

适合:固定发版周期(季度发版)、多版本并行维护、SaaS 产品。缺点:分支多、流程重,不适合持续部署。

GitHub Flow(轻量化):

1
2
3
main ————————————————
\ /
feature ——PR—

所有 feature 通过 PR 合并到 main,main 永远可发布。适合:SaaS、互联网产品、CI/CD 流水线。

Trunk-based Development(主干开发):

1
2
3
main ————————————————————————
\ / \ /
feature branches(短命< 1 天)

所有人频繁 merge 到 main,feature 分支存活不超过一天,强烈依赖 CI 和 feature flag。适合:Google、Facebook 这种超大规模工程。

维度 GitFlow GitHub Flow Trunk-based
分支复杂度 极低
发版频率 季度 随时 持续
CI/CD 要求 极高
团队规模 10-100 5-50 50+
适用产品 传统软件 互联网产品 云原生服务

十、踩坑记录

踩坑 1:rebase 后 push -f 的协作灾难

某同事对 main 分支 rebase 后 git push -f,导致 20 个同事的本地 main 都指向旧 commit,下午 3 点开始整个团队无法 push,5 点才用 reflog 恢复。对策:CI 配置禁止 force push 到 main/develop;本地用 --force-with-lease

踩坑 2:reflog 救援

1
2
3
4
5
6
7
# 误操作后看历史
git reflog
# a1b2c3 HEAD@{0}: rebase finished# d4e5f6 HEAD@{1}: rebase started
# 8h7i9j HEAD@{2}: commit: fix bug

# 回到 rebase 之前的状态
git reset --hard 8h7i9j

reflog 默认保留 90 天,90 天内的 commit都能找回。

踩坑 3:merge commit 撤销

1
2
3
4
5
# 撤销普通 commit
git revert <commit-hash>

# 撤销 merge commit,需要指定 -m1(保留主分支)
git revert -m 1 <merge-hash>

十一、小结:决策树 + 团队规范模板

个人决策树

1
2
3
4
5
是已推送的共享分支吗?
├─ 是 → 用 merge(不要 rebase)
└─ 否 → 是本地 feature?
├─ 是 → 用 rebase(保持线性)
└─ 否 → 用 merge --no-ff

团队规范模板

  1. main / develop 受保护,CI 禁止 force push
  2. feature 分支命名:feature/<jira-id>-<desc>,存活< 7 天
  3. PR 合并前必须 rebase 一次 main,解决冲突后再提
  4. merge统一用 --no-ff,保留分支信息
  5. tag 必须从 merge commit 切,不从 rebase commit 切
  6. 紧急 hotfix 直接 merge 到 main + 同步回 develop
  7. CI 配置 git push --force-with-lease 钩子,防止误覆盖

把这两条规则刻进团队 onboarding:本地随便 rebase,公共分支永远 merge。git log 干净了,git blame 准确了,git bisect 能用了——这就是版本控制该有的样子。


git rebase vs merge 深度对比:何时用哪个 / 团队协作规范
https://blog.calcguide.tech/2026-08-10-git-rebase-vs-merge深度对比/
作者
王争气
发布于
2026年8月10日
许可协议