Git merge vs rebase
merge 保留真实历史,rebase 重写提交历史,让历史更线性。
- 合并两个分支
- 通过创建一个 新的 merge commit
- 不修改已有提交
A---B---C (main)
\
D---E (feature)
执行:
git checkout main
git merge feature
结果:
A---B---C-------M (main)
\ /
D---E--- (feature)
M是一个 merge commit
✅ 优点
- 保留完整、真实的历史
- 安全,不会破坏已有提交
- 适合多人协作、公共分支
❌ 缺点
- 历史可能“分叉 + 合并”,较乱
- merge commit 多了之后不直观
- 把一个分支的提交“搬到”另一个分支后面
- 实际是:重新生成一组新的提交
A---B---C (main)
\
D---E (feature)
执行:
git checkout feature
git rebase main
结果:
A---B---C---D'---E' (feature)
D'、E'是 新提交(hash 已变)
✅ 优点
- 提交历史线性、干净
- 更容易阅读
git log - 非常适合本地整理提交
❌ 缺点
- 会改写历史
- 不当使用会影响他人分支
- 公共分支上风险高
| 维度 | merge | rebase |
|---|---|---|
| 是否改写历史 | ❌ 否 | ✅ 是 |
| 是否生成新提交 | ✅ merge commit | ❌(但会重建提交) |
| 历史是否线性 | ❌ | ✅ |
| 是否安全 | ✅ 高 | ⚠️ 需谨慎 |
| 适合公共分支 | ✅ | ❌ |
| 适合本地整理 | 一般 | ✅ |
✅ 强烈推荐 merge 的场景
main / master / release分支- 已推送到远端的分支
- 多人协作的共享分支
- CI / GitLab / GitHub 自动合并
示例:
git checkout main
git merge feature
✅ 推荐 rebase 的场景
- 本地 feature 分支
- 提交前整理 commit
- 不影响他人的私有分支
示例(最常见):
git checkout feature
git rebase main
已经 push 到远端、并且别人可能基于它工作的分支,禁止 rebase。
如果你 rebase 了并强推:
git push --force
别人就会遇到:
- 提交丢失
- 冲突爆炸
- 历史对不上
git rebase -i HEAD~5
可以:
- 合并提交(squash)
- 修改提交信息(reword)
- 删除提交(drop)
git pull --rebase
等价于:
git fetch
git rebase origin/main
👉 避免产生无意义的 merge commit
| 场景 | 推荐 |
|---|---|
| 本地开发 | rebase |
| 推送前 | rebase(整理提交) |
| 合并到主分支 | merge |
| CI / 发布分支 | merge |
| 个人仓库 | rebase 为主 |
merge 会生成一个新的合并提交,保留完整历史,适合公共分支;
rebase 会重写提交历史,使历史线性,适合本地分支整理。
已经推送到远端的分支不应使用 rebase。