git merge --no-ff 是保留分支历史的明确选择:强制创建合并提交,清晰标记分支交汇点,完整保留源分支所有原始提交,避免快进合并导致的历史丢失与回滚困难。

git merge --no-ff 是保留分支历史的明确选择
默认情况下,git merge 在目标分支没有新提交时会走 fast-forward 模式:直接移动指针,不产生新提交,也就看不到“这次是合并了 feature 分支”这个动作。用 --no-ff 强制创建一个合并提交,就能在历史里清晰标记出分支交汇点。
常见错误现象:git log --oneline 看不到 merge 提交,误以为分支没合进去;回滚时找不到合并边界。
- 必须先切换到目标分支(如
git switch main),再执行git merge --no-ff feature - 合并后
git log --graph --oneline --all能看到分叉+汇合结构,feature的所有原始 commit 都完整保留在图中 - 如果已发生 fast-forward 合并,无法事后补上
--no-ff—— 历史已不可逆
git merge --squash 会丢弃源分支历史
--squash 不是“保留历史”的方案,而是“只取结果、不要过程”。它把源分支所有变更打包成一次暂存区修改,不保留任何原始 commit ID、作者、时间戳或 message。
使用场景:临时集成某个实验性分支,或上游分支历史混乱、你只信任最终代码状态。
- 执行后必须手动
git commit,否则无提交 -
git log里完全看不到源分支的 commit,只有你这次的新提交 - 后续想追溯某行代码是谁在哪次提交改的?
git blame会指向这个 squash 提交,而非原始作者
rebase 本质是重写历史,不是保留历史
git rebase 把源分支的 commit 逐个复制到目标分支顶端,生成全新 commit ID。原始 commit 被丢弃,历史变成线性,但“谁在哪个分支上做了什么”这个上下文彻底丢失。
容易踩的坑:对已推送到远程的分支执行 rebase,会强制覆盖远端历史,协作成员 fetch 后需手工处理冲突,极易出错。
- 仅适合本地未共享的分支(如刚建的
fix/login-bug) - 执行后
git reflog还能查到旧 commit,但git log和远程仓库里都不可见 - 若团队要求审计可追溯(比如合规审查),
rebase不满足要求
--allow-unrelated-histories 是绕过保护,不是保留策略
当出现 refusing to merge unrelated histories 错误时,加 --allow-unrelated-histories 只是让 Git 允许合并两个毫无共同祖先的分支。它本身不决定如何保留历史 —— 后续仍取决于你用的是 merge、rebase 还是 --squash。
典型误用:以为加了这个参数就等于“安全合并”,其实只是跳过了 Git 的第一道防护。
- 加了该参数后,
git merge仍会创建 merge commit,源分支历史照常保留 - 但若源分支是另一个独立项目(比如从 SVN 导入的旧库),强行合并可能导致文件重复、配置冲突等逻辑问题
- 建议先用
git diff branch-a branch-b --name-only确认差异范围,再决定是否真要合并
--no-ff 是最轻量、最协作友好的方式;其余选项要么丢记录,要么改记录,得看清楚代价再动手。











