.gitignore 不生效的排查方法
.gitignore 不生效最常见原因:文件已被 Git 跟踪(需 git rm --cached 移出索引)。其他原因:规则语法错误、文件路径层级不对、前面有 ! 取反规则覆盖。用 git check-ignore -v <文件> 定位匹配的规则行。
最常见的原因只有一个:文件已经被 Git 跟踪了。 .gitignore 只对"未跟踪"文件生效——已进索引的文件加进 gitignore 照样被跟踪。解决:git rm --cached <文件> 移出索引后提交。其次才是规则写法问题,用 git check-ignore -v 定位。
原因一:文件已被跟踪(90% 的情况)
# 移出索引但保留本地文件
git rm --cached secret.env
git rm -r --cached node_modules/ # 目录递归
git commit -m "停止跟踪已被 gitignore 排除的文件"
提交后 gitignore 规则才开始生效。
原因二:规则写法问题
log # 匹配任何层级的 log 文件或目录
/log # 只匹配根目录下的 log
logs/ # 只匹配目录
*.log # 匹配所有 .log 结尾
logs/*.log # 只匹配 logs 直接子级,不含更深层
logs/**/*.log # 匹配 logs 下所有层级
原因三:规则被覆盖
后面的规则覆盖前面的,! 取反可能把你刚排除的又放行了:
*.log
!important.log # 这条让 important.log 不被忽略
定位工具
git check-ignore -v path/to/file
# 输出:.gitignore:12:*.log path/to/file
# 含义:.gitignore 第 12 行的 *.log 规则匹配了它
无输出 = 没有任何规则匹配(文件未被忽略)。git status --ignored 可总览全仓被忽略的文件。
常见问题(FAQ)
Q:为什么子目录里的 .gitignore 管不了别的目录?
设计如此:每个 .gitignore 只作用于它所在目录及其子目录。根目录的 .gitignore 才能覆盖全仓。
Q:全局 gitignore 不生效?
确认配置了路径:git config --global core.excludesFile ~/.gitignore_global;同样只作用于未跟踪文件。
Q:想让 Git 暂时忽略某个已跟踪文件的本地改动?
那不该用 gitignore,用 git update-index --skip-worktree <文件>(恢复用 --no-skip-worktree)。适合本地配置微调不想提交的场景。