git merge会生成含两个父提交的合并提交,真实记录分支交汇;git rebase则重放提交、重写历史,生成全新哈希的线性提交,不产生合并提交。

git merge 会生成合并提交,而 git rebase 不会
执行 git merge 时,Git 会找到两个分支的最近共同祖先,把当前分支和目标分支的差异合并,再创建一个新提交(即 merge commit),这个提交有两个父提交。它真实记录了“两条线在此交汇”的事实。
git rebase 则完全不同:它不新增提交,而是把你当前分支上、从共同祖先之后的所有提交,一个个“剪切”下来,重新应用到目标分支最新提交之后,生成一批哈希值全变的新提交(如原 abc123 变成 def456)。整个过程没有 merge commit,历史变成一条直线。
常见错误现象:
- 误在已推送到远程的公共分支(如
main)上执行git rebase,导致团队其他成员拉取时出现“找不到原始提交”“refusing to merge unrelated histories”等报错 - 用
git merge频繁同步上游,feature 分支里堆满Merge branch 'main' into feature提交,日志难以阅读
什么时候该用 git merge,什么时候必须用 git rebase
核心判断依据不是“哪个更高级”,而是“这个分支是否已被他人基于它继续开发”。
推荐做法:
- 向公共分支(
main、develop)合入代码 → 必须用git merge - 本地 feature 分支想同步
main最新改动 → 优先用git rebase main - 多人协作中,你自己的分支尚未推送到远程 → 可安全
rebase整理提交(比如把“修复 typo”“调整注释”等琐碎提交压缩掉) - 已执行过
git push的分支,哪怕只有你自己用,只要别人可能git fetch过 → 禁止rebase
性能影响很小,但兼容性风险极高:rebase 后强制推送(git push --force-with-lease)可能覆盖他人基于旧提交做的工作,尤其在 CI/CD 流水线已触发构建的情况下,后果比看起来更严重。
冲突解决方式完全不同:merge 一次搞定,rebase 可能反复卡住
git merge 把两个分支所有变更一次性对比,冲突只在合并时集中暴露,解决完提交一次即可完成操作。
git rebase 是逐个重放你的每个提交,每遇到一个与目标分支有重叠修改的提交,就暂停并要求你解决冲突;解决后要 git add + git rebase --continue,重复多次。如果 feature 分支有 12 个提交,而其中 3 个都碰到了冲突,你就得手动介入 3 次。
使用场景提示:
- 如果你的 feature 分支提交粒度细、自测频繁(例如每改一个函数就 commit 一次),
rebase时大概率反复冲突,不如先git merge同步,再用git rebase -i交互式压缩整理本地提交 - CI 脚本里绝对不要写
git rebase,它无法自动处理冲突,会导致流水线卡死或跳过关键检查
历史可追溯性 vs 历史可读性:这不是非此即彼的选择题
很多人以为“rebase 让历史干净 = 更好”,其实是在牺牲关键上下文。比如某次 bug 是因为合并时未注意某个配置项被另一分支改了——merge 提交里保留了两个分支的完整路径,能快速定位谁、何时、在哪条线上动了哪行;rebase 后只剩一条线,那个配置项“仿佛天生就在那里”,排查时容易绕弯路。
真正需要警惕的是“混合滥用”:有人先 rebase 再 merge,结果远程 main 上既有一堆线性提交,又夹杂几个孤立的 merge commit,反而比纯 merge 更难理解。
最容易被忽略的一点:Git 日志工具(如 git log --graph、IDE 的 Git Graph)对两种历史的渲染逻辑不同。线性历史看着清爽,但一旦出问题,你得靠 git reflog 才能找回被 rebase “删除”的原始提交——而很多新人根本不知道 reflog 存在。


















