.gitignore规则只对未跟踪文件生效;已跟踪文件需先执行git rm --cached移除追踪,再提交才能忽略。

Git 会按优先级和路径上下文匹配 .gitignore 规则,不是写上就生效——尤其已跟踪的文件不会被新规则影响,必须先 git rm --cached。
为什么改了 .gitignore 还是看到文件在 git status 里?
因为 Git 只对「未跟踪(untracked)」文件应用 .gitignore;一旦文件已被 git add 过(即处于暂存区或已提交),后续加的忽略规则完全无效。
- 确认文件状态:
git ls-files --cached <file>返回结果说明它已被跟踪 - 解除跟踪但保留本地文件:
git rm --cached <file>(单个)或git rm -r --cached <dir>(目录) - 执行后记得提交:
git commit -m "remove <file> from tracking" - 如果只是临时跳过检查(比如调试时),可用
git update-index --skip-worktree <file>,但慎用,它不随 clone 同步
**、* 和 / 在路径匹配中到底怎么起作用?
三者语义不同,混用会导致漏忽略或误忽略:
-
*不跨目录:例如log*.txt匹配app/log1.txt,但不匹配app/logs/error.txt -
**可跨任意层级:例如src/**/test_*.py匹配src/test_utils.py、src/api/v1/test_main.py、src/utils/tests/test_helper.py - 开头的
/表示从项目根开始:例如/dist只忽略项目根下的dist/,不忽略src/dist/;而dist/(无前导 /)会匹配所有目录下的dist/ - 结尾的
/明确只匹配目录:build/忽略所有名为build的文件夹,但不影响同名文件build
全局、项目级、本地 exclude 文件的优先级和适用场景
Git 检查忽略规则的顺序是:命令行参数 → 当前目录及父目录的 .gitignore → .git/info/exclude → 全局 core.excludesfile。后加载的规则可覆盖前面的同名匹配。
- 项目共享规则(如
*.pyc、/node_modules):写进项目根目录的.gitignore,提交到仓库 - 仅本机本项目需要(如 IDE 临时文件
.vscode/或构建产物/out):写进.git/info/exclude,不提交,也不影响他人 - 全系统通用(如 macOS 的
.DS_Store、编辑器备份*~):配置全局文件,例如git config --global core.excludesfile ~/.gitignore_global,然后往该文件里加规则 - 注意:
.git/info/exclude的路径基准是项目根目录,和.gitignore一样;但它的规则不会被传播,适合个性化调试
! 否定规则为什么有时完全没用?
! 只能“恢复”已被前面规则排除的文件,但它无法穿透已排除的父目录——Git 根本不会遍历被忽略的目录,自然看不到里面的 ! 规则。
- 错误写法:
/build/→!/build/config.json→config.json依然被忽略(因为/build/目录被跳过) - 正确做法:要么去掉
/build/改为更细粒度控制,如/build/*.log,再!/build/config.json;要么用!build/先取消整个目录忽略,再逐个排除子项 - 另一个陷阱:
**/temp之后写!important/temp是无效的,因为**/temp已经匹配并忽略了所有temp,important/temp属于更具体的路径,但匹配顺序是“最后一条生效”,所以得把!important/temp写在**/temp前面
最常被忽略的一点:规则生效依赖 Git 缓存状态和路径解析上下文,不是纯文本匹配。改完 .gitignore 后务必用 git check-ignore -v <file> 验证实际命中哪条规则——这是定位问题最快的方式。


















