不会。快进合并仅移动分支指针,不产生新提交;仅当目标分支无新提交、历史呈线性时触发,合并后无合并提交节点,git log 和 git show 均显示被合并分支的最新提交,不保留合并动作本身记录。

快进合并(fast-forward)到底会不会产生新提交
不会。快进合并只是移动当前分支指针,不创建任何新提交节点。
触发条件很明确:目标分支(比如 main)自你从它创建待合并分支(比如 feature)后,没有任何新提交。此时 feature 的提交历史完全包含 main,Git 认为“只需把 main 指针往前推到 feature 最新提交即可”。
- 执行
git merge feature后,git log --oneline看不到额外的合并提交 -
git show HEAD显示的是feature上最后一个提交的内容,不是合并动作本身 - 分支图是直线,
git log --graph不会出现分叉与汇合点
容易踩的坑:你以为合并了功能,结果发现 main 上根本没留下“这次合并来自哪个分支”的痕迹——审计、回滚、排查问题时会少一层上下文。
非快进合并(--no-ff)为什么必须显式加参数
因为 Git 默认优先走快进,除非检测到冲突或历史分叉,否则不会主动创建合并提交。
想强制保留合并记录(比如 CI 流水线需要标记某次发布集成了哪些功能),就得用 --no-ff:
-
git merge --no-ff feature:哪怕满足快进条件,也一定生成一个merge commit -
git config --global merge.ff false:全局禁用快进,所有git merge都等价于加了--no-ff - 不加参数又不满足快进条件时,Git 自动 fallback 到三方合并(three-way merge),也会生成
merge commit
注意:--no-ff 不解决冲突,只控制是否生成合并提交;冲突仍需手动处理并 git add + git commit。
合并提交(merge commit)的父提交怎么看
一个标准的非快进合并提交有两个父提交:一个是当前分支合并前的 HEAD,另一个是被合并分支的最新提交。
使用四维度框架评估任意 GitLab MR 或 GitHub PR 的复杂度:规模(20%),认知负荷(30%),审查工作量(30%),风险/影响(20%)...
验证方式很简单:
-
git show --pretty=%P -s HEAD输出两个 SHA-1 值,顺序是“当前分支旧 HEAD”在前,“被合并分支 HEAD”在后 -
git cat-file -p HEAD | grep parent也能看到两行parent行 - 在 GitHub/GitLab 页面上点开该合并提交,会明确列出 “Merge branch 'feature' into 'main'” 和两个父提交链接
这个双父结构是 Git 追溯分支来源的关键。如果用了 --squash 或 rebase,就只剩单父,分支归属信息就断了。
什么时候该用 --ff-only 而不是默认 merge
当你想确保“这次合并绝不能改写历史、也不能引入意外分叉”,就用 --ff-only。
典型场景:
- CI/CD 流水线中自动合并 PR:只允许线性集成,否则直接失败,避免人工介入
- 发布分支(如
release/v2.1)向main合并前做预检:防止误操作导致非线性历史污染主干 - 团队约定“功能分支必须先 rebase 到最新
main再提 PR”,这时--ff-only是验证前提是否满足的开关
执行 git merge --ff-only feature 失败时,错误信息固定是:fatal: Not possible to fast-forward, aborting. —— 看到这个,就知道得先 git pull origin main 再重试,或者换用 --no-ff。
真正容易被忽略的不是命令本身,而是“谁在什么阶段有权决定用哪种模式”。开发人员本地 merge 用 --no-ff,CI 脚本里用 --ff-only,而仓库保护规则可能禁止 push 含多个父提交的 commit——这些约束一旦错位,就会卡在最不该卡的地方。

















