根本原因是Git的忽略规则仅控制未跟踪文件的自动添加,不保护已存在但被.gitignore忽略的文件免于merge覆盖;其设计逻辑是只要文件存在于工作目录且对方分支有同名变更,Git就会尝试操作该文件。

合并时工作区忽略文件被覆盖,根本原因是什么
Git 在执行 git merge 时,只要目标分支修改了「当前工作区已存在但被 .gitignore 忽略的文件」,就会尝试将其纳入合并过程——哪怕它从没被 Git 跟踪过。Git 不区分“被忽略但存在”和“被跟踪但暂存”,只要文件在工作目录里,且对方分支有同名路径的变更(比如对方删了该文件,或改了内容),Git 就会报冲突或直接覆盖。
这不是 bug,是设计行为:Git 的忽略规则只影响「未跟踪文件的自动添加」,不保护已存在文件免于合并操作。
常见现象包括:
- 你本地有个
config.local.json(在.gitignore里),对方分支删掉了这个文件,你git merge main后它消失了 - 对方分支新增了
logs/error.log(被忽略),你本地也有同名文件,merge 后你的内容被清空或替换成对方空文件
如何阻止 merge 时覆盖本地忽略文件
最稳妥的方式是让 Git 明确知道:“这个文件我不管,别动它”。用 git update-index --skip-worktree 标记:
操作步骤:
- 确认文件确实被忽略:
git check-ignore -v config.local.json(应输出匹配规则) - 标记跳过工作区检查:
git update-index --skip-worktree config.local.json - 验证状态:
git ls-files -v | grep ^S(带S前缀即生效)
--skip-worktree 是本地仓库级设置,不随 clone 传播;换机器或重装需重新标记。不要用 --assume-unchanged,它仅用于性能优化,对 merge 行为无实质影响。
merge 已发生覆盖后怎么恢复
如果已经执行了 merge,且忽略文件内容丢失,别急着 git checkout——它不会还原未跟踪文件。
恢复方法取决于你是否还保留原始内容:
- 若文件内容刚删/刚改,且没关编辑器:直接从编辑器里恢复(多数 IDE 有本地历史)
- 若已关闭编辑器,但系统有文件快照(如 macOS Time Machine、Windows 文件历史):优先从此恢复
- 若啥都没留,且该文件本就来自模板(如
config.example.json):复制模板重填,这是最常被忽略的兜底动作
git restore 或 git reflog 能找回它。
长期规避:把敏感忽略文件转成模板 + 生成逻辑
靠人工标记 --skip-worktree 容易漏,尤其多人协作时。更可持续的做法是解耦「模板」和「实例」:
例如处理配置文件:
- 提交
config.example.json到仓库(不忽略) -
.gitignore加一行:config.local.json - 写个简易脚本(
setup.sh或npm run init-config),自动cp config.example.json config.local.json - 所有代码读取
config.local.json,但绝不写入或提交它


















