When a file disappears from Git's untracked-file listing, inspect the rule responsible before editing ignore files. git check-ignore can report the source file, line number and matching pattern. Its quiet mode also provides an exit status suitable for a script.
This tutorial creates a disposable repository containing one broad log-file rule and one exception. It demonstrates that verbose output can include a negated pattern, so the presence of an output line alone is insufficient to conclude that the path is ignored.
Prerequisites
Use Git, Bash and standard Linux command-line utilities. Run in a writable scratch directory. Save this program as ignore.sh and execute it with Bash. It creates no commits and configures no account identity.
#!/usr/bin/env bash
set -euo pipefail
root=$(mktemp -d "$PWD/ignore-demo.XXXXXX")
trap 'rm -rf -- "$root"' EXIT
cd "$root"
git init -q
printf '*.log\n!important.log\n' > .gitignore
: > debug.log
: > important.log
: > notes.txt
git -c core.excludesFile=/dev/null check-ignore -v -- debug.log important.log
if git -c core.excludesFile=/dev/null check-ignore -q -- debug.log; then
printf 'debug.log ignored\n'
else
exit 1
fi
if git -c core.excludesFile=/dev/null check-ignore -q -- important.log; then
exit 1
else
status=$?
test "$status" -eq 1
printf 'important.log included\n'
fi
if git -c core.excludesFile=/dev/null check-ignore -q -- notes.txt; then
exit 1
else
status=$?
test "$status" -eq 1
printf 'notes.txt has no ignore match\n'
fi
Run and expected output
bash ignore.sh
.gitignore:1:*.log debug.log
.gitignore:2:!important.log important.log
debug.log ignored
important.log included
notes.txt has no ignore match
The separator before each path in the first two lines is a tab; it is displayed as spacing above.
Read the evidence
The first line explains that debug.log matches the broad rule on line one. The second shows the later exception for important.log. The quiet checks establish that debug.log is ignored while important.log is not. notes.txt has neither a matching positive rule nor an exception.
Each command supplies core.excludesFile=/dev/null for that invocation only, preventing a personal global exclude file from changing the fixture's result. It does not write configuration. The absolute temporary-directory path allows the exit trap to remove the correct directory even after cd enters it.
Edge cases and troubleshooting
Quiet mode returns zero for an ignored path and one when the path is not ignored; errors must not be treated as an ordinary negative result. The script verifies status one in its negative branches. Placing these commands inside if statements also avoids premature termination from set -e on an expected status one.
In an existing repository, tracked files are normally omitted from check-ignore's analysis. The documented --no-index option can help inspect pattern behavior independently of tracking. An ignore rule does not remove a file already tracked in the index.
Nested .gitignore files and excluded parent directories introduce additional precedence rules. Diagnose the exact path rather than assuming a rule in the root file wins. This script tests only the newly created untracked files and cleans up that disposable repository on exit.
Primary references
Consult git-check-ignore for output and exit status, and gitignore for pattern precedence. Browse more Git tutorials.