必须用git merge --no-ff时:合并功能/发布/热修复分支到main或develop,需明确标记集成动作、保留分支生命周期、满足审计与ci回溯需求;它强制生成合并提交,避免快进导致历史丢失。

什么时候必须用 git merge --no-ff
当你要把一个功能分支(比如 feature/login)合并进 main 或 develop,且团队需要明确知道“这次是一次集成动作”,就必须加 --no-ff。不是为了好看,而是日志里一旦缺了这个合并提交,你就再也分不清哪些提交属于哪个功能周期。
常见错误现象:git log --oneline 看起来是线性一串,feature 分支像“被吃掉”了一样,查不到它从哪来、到哪止;CI/CD 流水线触发后回溯失败,因为没法定位合并点。
- 适用场景:功能分支、发布分支(
release/*)、热修复分支(hotfix/*)合并进主干 - 不适用场景:临时调试分支、个人实验分支、或你明确知道该分支只用于本地验证且永不进主干
- 参数差异:
--no-ff不影响代码内容,只影响提交图谱;它和--squash互斥,不能同时用
git merge --no-ff 会强制生成新提交,但你得填好提交信息
执行 git merge --no-ff feature 后,Git 一定会打开编辑器让你写提交信息——这不是可跳过的步骤,也不是默认填个空就行。这个提交信息就是未来所有人看历史时的第一眼上下文。
容易踩的坑:git merge --no-ff -m "merge" 这种写法虽然能过,但等于放弃语义。下次有人 git show <merge-commit></merge-commit>,看到的只有“merge”,完全无法判断这是登录功能上线、还是支付链路重构。
- 建议格式:
-m "merge feature/payment-v2: add Alipay support and retry logic" - 如果信息复杂,别硬塞在命令行里,让编辑器打开后手动写清楚变更范围、风险点、关联 issue 编号
- 注意:加了
--no-ff后,--no-commit依然有效,可以先合并暂不提交,适合需要检查工作区状态再落库的场景
为什么 --ff-only 和 --no-ff 不能混用
--ff-only 的意思是“只允许快进,否则报错”,而 --no-ff 是“禁止快进,必须建新提交”。两者逻辑直接冲突,Git 会拒绝执行并提示 fatal: --ff-only can be used only with --ff(实际报错信息含 --ff,即 fast-forward 的缩写)。
真实使用中,有人想“优先快进,不行再走 --no-ff”,但 Git 没提供这种 fallback 机制。你得自己判断:
- 先跑
git merge --ff-only feature,如果失败(报错),说明有分叉,再补git merge --no-ff feature - 或者干脆统一策略:所有正式合并都走
--no-ff,省去判断成本 - CI 脚本里尤其要避免尝试
--ff-only后续又切回--no-ff,容易因并发 push 导致 HEAD 偏移,引发意外冲突
合并后怎么看效果?别只信 git log
git log --oneline 看不出是否用了 --no-ff,它只显示提交哈希和消息。真正要看分支结构,得用带图谱的命令:
正确验证方式:git log --graph --oneline --all。如果看到类似这样的结构:
* e1e9c68 (HEAD -> main) merge with no-ff |\ | * f52c633 (feature/login) add login form validation |/ * cf810e4 conflict fixed
说明成功了——那个带 | \ 和 | / 的节点就是 --no-ff 生成的合并提交。
容易忽略的点:如果远程已有别人推送的提交,你本地合并完直接 git push 可能失败(因非快进)。此时必须先 git pull --rebase 或 git pull --no-rebase 拉取最新,再推——而后者会把你的合并提交也一起带上,确保远端历史完整。











