git status只显示“both modified”是因为冲突检测是文件粒度而非行粒度,仅预警文件被双方修改且区域重叠,具体冲突行需合并执行后才标记。

冲突发生前,git status 为什么只显示“both modified”而不标出具体行?
因为 Git 的冲突预警是“文件粒度”的,不是“行粒度”的。它只负责告诉你:这个文件在两个分支里都被改过,且改动区域重叠,无法自动裁决。它不会提前解析哪几行有冲突——那是合并执行后才生成的标记。
所以 git status 输出中出现 both modified: src/utils.js,就是最明确的预警信号。此时还没真正合并,但已可预判风险。
- 别等
git merge报错才行动;看到both modified就该暂停,先用git diff HEAD...origin/main -- src/utils.js对比双方修改范围 - 如果改动集中在同一函数或配置块,基本 90% 会冲突;如果一个改顶部注释、一个改底部导出,大概率能自动合并
- TortoiseGit 或 IDEA 在右键“Merge”前会弹窗列出待合并文件,并高亮标红已存在
both modified的项——这就是图形化预警入口
如何用 git merge --no-ff + 预检脚本拦截高风险合并?
默认 git merge 是快进式(fast-forward),不产生合并提交,也就没有机会插入检查逻辑。强制使用 --no-ff 后,每次合并都生成一个明确的合并提交,你就能在 CI 或本地钩子里加预检。
例如,在 .git/hooks/pre-merge-commit 里写:
#!/bin/sh
conflict_files=$(git status --porcelain | awk '$1 == "UU" {print $2}')
if [ -n "$conflict_files" ]; then
echo "❌ 检测到未解决的冲突文件:$conflict_files"
echo "请先处理冲突,再运行 git add && git commit"
exit 1
fi
-
UU是git status --porcelain中表示“未合并(unmerged)”的标志,比肉眼扫both modified更可靠 - 这个钩子只在真正要创建合并提交前触发,不影响
git pull或git rebase - 注意:Windows 下需用 PowerShell 或 Git Bash 运行,CMD 不支持该钩子
IDEA 里“Merge into Current Branch”按钮点击后闪退?其实是冲突预警被静默吞掉了
这不是 BUG,是 IDEA 的设计妥协:当检测到潜在冲突时,它不会弹窗阻断,而是直接切到“Merge Conflicts”工具窗口,但这个窗口默认不自动聚焦,容易被忽略。你可能点了合并,看状态栏没报错就以为成功了,其实后台已卡在冲突状态。
- 打开
Settings > Version Control > Git,勾选Warn when merging into branch with conflicts—— 这会让 IDEA 在点击合并前弹确认框 - 冲突发生后,务必检查右下角是否出现黄色提示条:“3 files with conflicts”,点开才能进真正的冲突编辑视图
- 千万别在冲突状态下用
Ctrl+K提交 —— 此时git commit会把
为什么 git pull --rebase 有时比 git merge 更早暴露冲突?
因为 git pull --rebase 是把你的本地提交“重放”到上游最新版上,每一条提交都会单独尝试应用。只要其中任意一条与上游改动重叠,就会立刻中断并提示冲突;而 git merge 是把整个分支差异一次性整合,冲突只在最后一步集中爆发。
- 这意味着:用
--rebase能把一个大冲突拆成多个小冲突,每个都更易定位和理解 - 但代价是:如果本地有 5 个提交,第 3 个就冲突了,那第 4、5 个根本不会执行,你得一个个手动 resolve +
git rebase --continue - 团队若统一约定用
--rebase,建议配合git config --global pull.rebase true,避免新人漏掉--rebase参数
真正难的不是解决冲突,是让冲突在代码写完前就被发现。预警机制的核心不是拦截,而是把“冲突即将发生”这个信息,推到开发者写完最后一行代码、敲下 git push 前的那一刻。











