guide

为什么被忽略?用 git check-ignore 调试

介绍如何用 git check-ignore -v、git status --ignored、git ls-files 找出忽略文件的规则,并排查规则不起作用的 7 个常见原因。

规则一多,就会出现“这个文件为什么看不到?”或“为什么一直显示?”这样的疑问。git 提供了回答这些问题的命令。

git check-ignore -v

git check-ignore -v logs/app.log src/build/keep.txt

输出格式为 来源:行号:模式<制表符>路径

.gitignore:3:*.log	logs/app.log

如果还想看未匹配的路径,请同时使用 --non-matching(-n)。

已跟踪的文件用 --no-index

已跟踪的文件不受忽略规则影响,因此 check-ignore 默认也不会输出任何内容。如果只想知道规则是否匹配该文件,请加上 --no-index

$ git check-ignore -v app.log            # 已被跟踪,因此无输出
$ git check-ignore -v --no-index app.log
.gitignore:3:*.log	app.log

查看被忽略的文件列表

# 连同状态一起显示被忽略的项目(以 !! 标记)
git status --ignored --short

# 按文件逐一列出所有被忽略的文件
git ls-files --others --ignored --exclude-standard

# 匹配忽略规则但仍被跟踪的文件
git ls-files -ci --exclude-standard

当整个目录被忽略时,git status --ignored 会像 !! logs/ 这样只显示一个目录。如果想按文件查看,请使用 ls-files

规则不起作用的常见原因

  1. 文件已被跟踪。 这是最常见的原因。如果 git ls-files <路径> 有输出,就说明它已被跟踪。用 git rm --cached 取消跟踪。
  2. 父目录已被排除。 在忽略了 dir/ 的情况下,!dir/file 不起作用。请改为 dir/*
  3. 顺序颠倒了。 如果否定规则之后又出现了范围更广的规则,后者会获胜。查看 check-ignore -v 输出的行号就能立即发现。
  4. 行尾空格。 *.log 末尾的空格会被去除,但反过来,模式前面的空格或全角空格等看不见的字符会作为模式的一部分保留。
  5. 斜杠方向。 即使在 Windows 上,gitignore 也只把 / 用作路径分隔符。build\output 中的反斜杠会被解释为转义,无法按预期工作。
  6. 误解锚定。 config/local.json 因为中间有斜杠,只匹配根目录下的 config。要作用于任意深度,请使用 **/config/local.json
  7. 大小写。core.ignorecasefalse 的环境(通常是 Linux)中,*.JPG*.jpg 是不同的。在 macOS、Windows 上创建的仓库通常为 true,因此可能出现本地有效而 CI 中无效的差异。

在浏览器中预先确认

如果想在应用到仓库之前修改规则并比较结果,本站的模式测试标签页很方便。粘贴规则和路径列表后,它会针对每个路径显示结果、决定规则(行号)以及因父目录而被忽略的情况。路径列表可以直接使用 git ls-filesfind . -type f 的输出。不过,包含下层目录的 .gitignore 和全局设置在内的最终判定,请在仓库中用 git check-ignore -v 确认。

参考

← 上一篇用 .gitignore 忽略已提交的文件