.gitignore pattern tester
Paste a .gitignore and a file path. See whether git ignores it, which line decided under last-match-wins, and the trap that bites everyone: a ! rule cannot re-include a file whose parent directory is already excluded.
analyzing…
Every rule, in file order
| ln | pattern | type |
|---|
The trap everyone hits
Git decides a path by the last matching pattern, and a ! prefix re-includes a file an earlier pattern excluded. So far, like CODEOWNERS. But there is one rule that breaks the symmetry, straight from man gitignore:
"It is not possible to re-include a file if a parent directory of that file is excluded."
Git does not descend into an ignored directory. If build/ is excluded, git never looks inside it, so !build/keep.txt on a later line has nothing to act on. The negation is dead. This tool walks each directory in the path from the top down, exactly as git does, and tells you the moment a parent directory ends the search, so you can see why a ! rule you expected to work never fired.
| token | meaning |
|---|---|
| pattern | ignore files and directories matching the pattern. |
| !pattern | re-include (negate) a match an earlier pattern excluded. Has no effect if a parent directory is already excluded. |
| /at end | match directories only. cache/ ignores a directory named cache (and everything in it), never a file named cache. |
| /at start | anchor to the root of the .gitignore. /dist matches only the top-level dist, not src/dist. |
| /in middle | a slash anywhere except the end also anchors the pattern to root. src/*.js is relative to the root. |
| no slash | floats. *.log or build/ matches at any depth. |
| * | matches anything except a slash, within one path segment. |
| ** | matches across directories. **/foo (foo anywhere), foo/** (everything under foo), a/**/b (a and b with anything between). |
| ? | matches any single character except a slash. |
| # at start | a comment line. Use \# for a pattern that starts with a literal hash. |
What this tool does not do
It models one .gitignore sitting at the repository root and tests one path at a time. It does not combine nested .gitignore files in subdirectories, .git/info/exclude, or the global core.excludesFile, and it does not read your working tree to know which paths are real directories (it infers a directory from a trailing / on the path, otherwise treats the last segment as a file). Bracket character classes like [a-z] are matched literally rather than as ranges. For the canonical rules, see git-scm.com/docs/gitignore. The sibling tools CODEOWNERS and robots.txt apply the same paste-rules-test-a-path idea to different precedence rules.
This is a single static HTML file with no network calls. Source: github.com/truffle-dev/tool-gitignore. MIT.