Polyatic gitignore-explain

gitignore‑explain

git check-ignore -v, but paste‑and‑see

1 .gitignore

2 Paths to check

One repo‑relative path per line. A trailing / marks a directory (needed for dir‑only rules like dist/); anything else is treated as a file.

3 Verdicts

Paste rules on the left and list paths below them — every path gets a verdict here instantly, no Generate button. Click a row to pin its deciding line in the source pane.

Honest limits

  • This tool does not read your repo. It models git’s documented matching (last match wins, parent‑directory exclusion beats negation, dir/ rules, ! re‑inclusion) for the one .gitignore you paste — it cannot know about files git already tracks, which git never ignores regardless of rules.
  • One root source only. The pasted rules are treated as the repo‑root .gitignore. Nested sub/.gitignore files are not resolved: the core treats every source as rooted at the repo root and does not rebase a nested file’s patterns relative to its own directory, so don’t paste one here and expect git’s answer.
  • Case‑sensitive, matching git on case‑sensitive filesystems (Linux): *.LOG does not match a.log. On default macOS/Windows filesystems git sets core.ignoreCase=true and matches case‑insensitively, so answers can differ there.
  • A path with a trailing / is checked as a directory; without one, as a file. Getting this wrong flips verdicts for dir‑only patterns — build/ ignores the directory build/ but not a file named build.
  • Malformed input (absolute paths, .. segments) returns the core’s structured error verbatim instead of a guessed verdict.

Your rules and paths never leave this browser: all matching runs locally, so nothing you paste is ever sent anywhere. It models git’s documented matching for one pasted .gitignore and does not read your repo. The page’s only network use is a single anonymous, self-hosted page-view count.

What this tool does — and its honest limits

What it does. This is git check-ignore -v as a paste‑and‑see page: paste your .gitignore, list some repo‑relative paths, and every path gets a verdict — ignored, not ignored, or re‑included — plus the exact line number and pattern that decided it. Click a verdict row and the deciding line lights up in the source pane. Everything recomputes live on every keystroke; there is no Generate button and nothing is uploaded.

Why real git semantics matter. Popular free web gitignore checkers run minimatch, a generic glob matcher that implements none of gitignore’s precedence rules: no “last matching pattern wins”, no negation ordering, and — the classic trap — no rule that a negation cannot re‑include a file when a parent directory of it is excluded. Worked example: with the two rules dist/ then !dist/keep.js, git still ignores dist/keep.js, because git’s own documentation says “It is not possible to re‑include a file if a parent directory of that file is excluded.” A minimatch‑based checker reports it as kept — a provably wrong answer you might ship a .gitignore on. This page also gets /‑anchoring precedence and dir‑only (build/ vs a file named build) right.

How it’s verified. The matching engine is golden‑tested against a real git binary: 11 golden vectors plus 30 adversarial vectors across ten edge‑case families (negation chains, ** positions, \#/\! escapes, trailing spaces, CRLF, case sensitivity…) are regenerated from actual git check-ignore -v output on every test run — 57 tests total. Per‑pattern glob matching is delegated to the vendored, pinned node‑ignore 5.3.2 (MIT); git’s precedence semantics are implemented on top.

Honest limits — read before trusting a verdict. (1) It models matching for the one .gitignore you paste and does not read your repo — in particular it cannot know about files git already tracks, which git never ignores regardless of rules. (2) Your global gitignore (core.excludesFile, e.g. ~/.config/git/ignore) and .git/info/exclude are not consulted. (3) Nested sub/.gitignore files are not rebased: the pasted rules are treated as the repo‑root .gitignore, so a nested file’s patterns would need rebasing before pasting. (4) Matching is case‑sensitive, like git on Linux (core.ignoreCase=false): *.LOG does not match a.log. On default macOS/Windows filesystems git folds case, so answers can differ there. (5) A trailing / on a checked path marks it as a directory; getting that wrong flips verdicts for dir‑only patterns. Malformed input (absolute paths, .. segments) returns a structured error instead of a guessed verdict.

The library ships with this page. The verdicts are produced by an MIT‑licensed CommonJS engine running entirely in this tab over the vendored node‑ignore matcher — the exact code that renders these verdicts is the library, and it ships with the page.