.gitignore 对已跟踪文件无效,须先用 git rm --cached 清除缓存;忽略目录但保留子项需用 ! 否定且顺序严格;路径前加 / 限定根目录匹配;全局忽略不作用于已提交文件;状态判断应优先使用 git status --ignored。

文件已被 Git 跟踪,.gitignore 完全不生效
这是最常被卡住的地方:改完 .gitignore,git status 里该出现的文件还在,甚至 git add -A 还会把它加回去。根本原因不是规则写错了,而是这个文件早被 git add 或 git commit 过——Git 把它标记为 tracked,此后 .gitignore 对它彻底失效。
必须先清除 Git 的缓存记录:
-
git rm --cached <file></file>(单个文件) -
git rm -r --cached <folder></folder>(整个文件夹,比如unpackage/)
执行后本地文件完好无损,只是从 Git 的“受控名单”里划掉。之后再 git add .,新规则才真正起作用。别跳过这步,否则所有高级技巧都是白搭。
忽略整个文件夹但保留某个子文件或子目录
典型场景:想忽略 src/logs/ 下全部内容,但保留 src/logs/keep.log;或者忽略 dist/,但保留 dist/public/ 子目录。关键在规则顺序和 ! 否定语法。
正确写法示例(放在项目根目录的 .gitignore 中):
src/logs/* !src/logs/keep.log dist/ !dist/public/
注意点:
- 否定规则
!必须写在对应忽略规则 之后,否则无效 -
dist/结尾带/表示只匹配目录,不会误杀同名文件;!dist/public/同理,确保只放行该目录及其内容 - 如果
dist/public/下还有子目录要一并保留,不用额外写规则——只要父目录没被忽略,Git 会自动递归跟踪其内容
/ 开头和不带 / 的路径,匹配范围完全不同
很多人以为 node_modules 和 /node_modules 差不多,其实差一个层级维度:
-
node_modules→ 匹配项目中任意位置的node_modules(如src/node_modules、test/node_modules) -
/node_modules→ 只匹配仓库根目录下的node_modules(即./node_modules) -
logs/*.log→ 匹配logs/目录下所有.log文件,但不匹配logs/sub/logs/error.log(因为*不跨/) -
logs/**/*.log→ 才能匹配多级子目录下的.log文件
漏掉开头的 / 是导致规则“太宽”或“太窄”的主因。调试时用 git check-ignore -v <file></file> 看实际匹配哪条规则,比猜快得多。
全局忽略和项目级忽略混用时的坑
你设了全局 .gitignore_global(比如忽略 .DS_Store),但老项目里它依然出现在 git status ——不是配置失效,而是这个文件早被提交过。全局规则只对 untracked 文件生效,对已 tracked 的完全不管。
团队协作更要警惕这点:
- 全局配置是个人行为,别人不一定有;依赖它会导致同事反复提交 IDE 临时文件
- 通用规则(如
*.swp、.env)必须写进项目级.gitignore,才能保证一致 -
.git/info/exclude是仓库私有规则,适合临时忽略构建产物,但它不进版本库,换机器就丢
真正难的从来不是写对一行规则,而是搞清当前文件到底属于 tracked、untracked 还是 ignored 状态。先用 git status --ignored 看全貌,再动手删缓存或调规则。











