Why Is It Ignored? Debugging with git check-ignore
How to find which rule ignores a file with git check-ignore -v, git status --ignored and git ls-files, and a checklist of 7 common reasons a rule does not work.
As rules pile up, questions arise: "Why can't I see this file?" or "Why does it keep showing up?" git has commands that answer them.
git check-ignore -v
git check-ignore -v logs/app.log src/build/keep.txt
The output format is source:line:pattern<TAB>path.
.gitignore:3:*.log logs/app.log
- The source is the file containing the rule. It is one of
.gitignore,sub/.gitignore,.git/info/excludeor the global file path. - The line number and pattern tell you exactly which line it is.
- If nothing is printed, the path is not ignored.
- With
-v, paths restored with!also show the negation rule, as in.gitignore:4:!keep.log keep.log. - For files whose parent directory is excluded, the directory's rule is shown. For example, if it is due to a
logs/rule, you get.gitignore:1:logs/ logs/keep.txt.
To also see paths that did not match, add --non-matching (-n).
Use --no-index for tracked files
Ignore rules do not apply to files that are already tracked, so by default check-ignore prints nothing for them either. If you only want to know whether a rule matches the file, add --no-index.
$ git check-ignore -v app.log # tracked, so no output
$ git check-ignore -v --no-index app.log
.gitignore:3:*.log app.log
Listing ignored files
# Show ignored entries along with status (marked !!)
git status --ignored --short
# List every ignored file individually
git ls-files --others --ignored --exclude-standard
# Tracked files that match ignore rules
git ls-files -ci --exclude-standard
When an entire directory is ignored, git status --ignored shows it as a single directory, as in !! logs/. To see individual files, use ls-files.
Common reasons a rule does not work
- It is already tracked. This is the most common. If
git ls-files <path>prints something, the file is tracked. Stop tracking it withgit rm --cached. - A parent directory is excluded. With
dir/ignored,!dir/filehas no effect. Change it todir/*. - The order is reversed. If a broader rule appears again after a negation rule, the broader rule wins. The line number from
check-ignore -vshows this right away. - Trailing whitespace. The space at the end of
*.logis stripped, but spaces before the pattern and invisible characters such as full-width spaces remain part of the pattern. - Slash direction. gitignore uses only
/as the path separator, even on Windows. Inbuild\outputthe backslash is interpreted as an escape, so it does not work as intended. - Misunderstanding anchoring.
config/local.jsonmatches onlyconfigat the root because of the slash in the middle. To apply it at any depth, use**/config/local.json. - Case. In environments where
core.ignorecaseisfalse(usually Linux),*.JPGand*.jpgare different. Repositories created on macOS or Windows are usuallytrue, which can lead to rules that work locally but not in CI.
Checking in the browser first
If you want to try out rule changes and compare results before applying them to the repository, this site's Pattern test tab is convenient. Paste your rules and a list of paths, and it shows for each path the result, the deciding rule (with line number), and whether it was ignored because of a parent directory. You can use the output of git ls-files or find . -type f as-is for the path list. However, confirm the final verdict, which combines .gitignore files in subdirectories and global settings, with git check-ignore -v in the repository.
References
- git-check-ignore official documentation
- git-status official documentation: --ignored
- git-ls-files official documentation
- Verified as of: 2026-09-23 (output format checked with git 2.50.1)