merge 和 rebase 都是把两个分支的代码合并到一起,但历史记录的形态完全不一样。
前提场景:
main:主分支
feature:开发分支,从 main 切出去之后,main 又有新提交。
main: A --- B --- C
feature: \--- D --- E
1. git merge(合并)
git checkout main
git merge feature
不会修改原有提交,新增一个「合并提交」
历史会保留两条分支完整轨迹,形成交叉分叉
main: A --- B --- C --- F(merge commit)
feature: \--- D --- E ----/
F 是自动生成的合并提交,记录这次合并行为。
✅优点
历史完整真实,能看到曾经有一个 feature 分支,什么时候合并进来
不会改写历史,不会改变原有 commit ID,适合公共分支(main/master)
冲突只在 merge 提交 F 处解决一次
❌缺点
提交图会很多分叉,log 看起来杂乱
大量小分支合并后,历史图错综复杂
适合:公共共享分支、release、main,多人一起 push 的分支优先用 merge。
2. git rebase(变基)
git checkout feature
git rebase main
把 feature 的提交 (D、E)摘下来,放到 main 的最新提交 C 后面,生成全新的 commit ID,旧的 D/E 还在但不再被分支指向。
变基之后:
main: A --- B --- C
feature: \--- D' --- E'
D'、E' 是新生成的提交,和原来 D/E 内容一样,但 hash 变了。 之后 main 再 fast‑forward 合并:
git checkout main
git merge feature
main 直接快进到 E',没有合并提交,历史是一条直线:
A --- B --- C --- D' --- E'
✅优点
提交历史干净线性,没有分叉,看 log 非常清爽
方便代码回溯,
git bisect查找 bug 非常友好
❌缺点
改写历史!commit hash 全部改变
如果分支已经推送到远程、别人也在这个分支开发,千万不要 rebase,会造成别人本地仓库巨大冲突。
rebase 过程中每一个提交遇到冲突,都要逐个解决,不是一次性解决。
适合:自己本地还没 push 的私有分支。不要在多人共享分支 rebase。
核心对比表
通俗比喻
merge:两条马路修个立交桥交汇,两条路都保留,修一个新路口。
rebase:把辅路拆下来,整个挪到主路尽头接上去,变成一条直马路,旧辅路痕迹抹掉。
团队最佳实践(主流规范)
公共分支 main/master:永远只用 merge,禁止 rebase
个人本地 feature 分支:开发阶段用 rebase main,保持本地干净,再 PR/MR 到 main
PR/MR 设置:GitHub/GitLab 可以设置:
merge:保留合并提交squash merge:把 feature 所有提交压扁成 1 个 commit 再合并rebase merge:服务端做 rebase 合并,生成线性历史
⚠️重要警告
永远不要对已经 push 到远程、其他人也在使用的分支执行 rebase! 如果已经 rebase 了本地,远程有旧版本,强制推送
git push -f会搞乱所有人仓库。
常见组合流程(日常开发)
# 在自己feature分支开发
git checkout feature
# 同步main最新代码到本地,变基,保持线性
git rebase main
# 解决完冲突后继续
git add .
git rebase --continue
# 推送自己的私有feature分支到远程
git push
# 然后提PR,main端用merge或者rebase‑merge
rebase 冲突中断后
git rebase --continue:解决完冲突继续git rebase --abort:放弃变基,恢复到 rebase 之前状态
本文原创作者:易君召,详见:https://www.yijunzhao.cn/authors/yijunzhao,转载请注明出处。
原文链接
欢迎访问 小易撩挨踢