The Complete Guide to .gitignore: Generator, Patterns, and git check-ignore Online
Every Git repository has a quiet gatekeeper: the .gitignore file. It decides which files Git should pretend do not exist — build output, dependency folders, log files, editor settings, secrets. Get it right and your repository stays clean, small, and safe to share. Get it wrong and you either commit megabytes of junk or, worse, leak an API key to a public repo. This guide explains how gitignore patterns actually work, how to compose a solid file with a gitignore generator like IgnorePilot, and how to verify your rules with a git check-ignore online simulator before they bite you.
What is a .gitignore file?
A .gitignore is a plain-text file, usually in the root of your repository, containing one pattern per line. Git consults it whenever it scans your working tree: any path matching a pattern is "ignored", meaning Git will not show it in git status, will not stage it with git add ., and will not complain about it being untracked. Ignored files are not deleted — they stay on your disk exactly where they are. Git simply agrees not to track them. You can also place .gitignore files in subdirectories; those apply to that directory and everything below it, which is handy for monorepos where the frontend and backend have different ignore needs.
Blank lines are skipped and lines starting with # are comments, so document your rules generously — future you will thank present you. Everything else is a pattern, and patterns follow a small but surprisingly subtle glob language.
How gitignore patterns work: the five rules that matter
1. A pattern without a slash matches by name, anywhere. *.log ignores every file ending in .log in the repository root and in every subdirectory. This is the rule most beginners rely on, and it is usually what you want for file extensions.
2. A slash in the middle (or at the start) anchors the pattern to the .gitignore location. doc/frotz ignores only doc/frotz relative to the gitignore file — not other/doc/frotz. A leading slash makes the anchoring explicit: /build matches the top-level build only.
3. A trailing slash means directories only. build/ ignores a directory named build and everything inside it, at any depth — but it will never ignore a file that happens to be named build. Without the slash, build matches both files and directories. This distinction is one of the most common sources of confusion, and it is why IgnorePilot's plain-English decoder calls it out explicitly.
4. Wildcards have directory-aware meanings. * matches any run of characters except /, ? matches exactly one character except /, and [abc] matches one character from a set or range. The double star ** is the power tool: a leading **/ matches in all directories (**/temp finds temp at any depth), a trailing /** matches everything inside a directory (logs/**), and a/**/b matches a/b, a/x/b, a/x/y/b, and so on.
5. Order matters: the last matching pattern wins. Git reads your rules top to bottom and the final pattern that matches a path decides its fate. This is what makes negation possible.
Negation rules: the ! exception
Prefixing a pattern with ! re-includes a path that an earlier rule ignored. The classic example is ignoring all logs but keeping one that matters: *.log followed by !keep.log. Because the last match wins, keep.log survives while every other log file stays ignored. Negations are also how teams keep placeholder files in otherwise-ignored folders: /tmp/* plus !/tmp/.keep is a pattern you will see in Rails projects everywhere.
But negation has a famous trap, and it is worth understanding because it surprises even experienced developers: git cannot re-include a file if one of its parent directories is excluded. If your rules say build/ and then !build/keep.js, the file build/keep.js stays ignored. Git skips the contents of ignored directories entirely for performance, so the negation never gets a chance to apply. The fix is to re-include the directory first (!build/) and then narrow down, or to ignore the directory's contents instead of the directory itself (build/*). IgnorePilot's check-ignore simulator detects this exact situation and tells you the parent directory is blocking your exception — a detail most online testers miss.
Why use a gitignore generator instead of copy-pasting?
Most developers start a project by googling "gitignore template node python" and pasting the first file they find. That works until your project is not a pure Node.js or pure Python project — which, in 2026, is almost always. A typical side project might be a Python API, a React dashboard, a Terraform deployment, and a LaTeX-written report living in one repository. Pasting four template files together by hand means duplicated lines, conflicting rules, and no easy way to check what you actually ended up with.
A proper gitignore generator solves the stacking problem: you pick the stacks you use, it merges the templates, removes exact duplicates, and hands you one clean file. IgnorePilot ships with 16 curated templates — Node.js, Python, Java, Go, Rust, Ruby, PHP, .NET, Swift/Xcode, Android, Flutter, Terraform, WordPress, LaTeX, Jupyter/data-science, and C/C++ — and lets you layer your own custom rules on top. The composer shows you live stats (how many rules, how many duplicates were removed) so the output stays reviewable, not a mysterious wall of text.
Verifying rules with git check-ignore online
Writing rules is only half the job; the other half is knowing what they actually match. The real git check-ignore command answers one question: "would git ignore this path?" You give it a path, it gives you the rule that decided. IgnorePilot recreates that behavior as a git check-ignore online tool with one big upgrade: a pattern-by-pattern trace. Instead of just the verdict, you see every rule in your file, whether it matched the path, and whether its effect was to ignore, re-include, or do nothing. When a path surprises you — and it will — the trace shows you exactly which line is responsible.
This turns gitignore from guesswork into a testable process. Before committing your file, run your trickiest paths through the simulator: the build output you want ignored, the one log file you want kept, the secrets directory that must never be committed. If the verdict is wrong, the trace tells you which pattern to fix, and the plain-English decoder translates that pattern into words you can reason about.
Common .gitignore mistakes (and how to avoid them)
Committing the file late. Gitignore only affects untracked files. If you already committed node_modules or a .env file, adding a rule later will not remove it from history — you need git rm --cached for that, and if secrets were involved, you should rotate them because they are in the history forever.
Ignoring too broadly. A rule like * or data/ can silently swallow files you meant to commit. Prefer specific patterns, and when you must use a broad one, add targeted ! exceptions — then test them in the simulator.
Forgetting OS and editor files. .DS_Store, Thumbs.db, .idea/, and .vscode/ have no business in a repository. Better yet, put them in your global gitignore (git config --global core.excludesFile) so every project on your machine is covered.
Committing secrets. This is the expensive one. A .env rule is cheap insurance, but pair it with a pre-commit check: if your repository is already public, assume anything ever committed is compromised.
One template for a polyglot repo. If your repo mixes stacks — say a gitignore template node python combination — generate a stacked file instead of picking one template and hoping. Each stack brings its own build folders, caches, and lockfiles.
Best practices for a clean repository
Start with the generator, then review: read through the composed file once and delete anything that does not apply — a smaller gitignore is easier to trust. Keep stack templates in labeled sections with comments, so the next contributor understands why *.tfstate is there. Commit the .gitignore file itself (it is meant to be shared), and treat changes to it like code: review the diff, run your test paths through the check-ignore simulator, and only then push. For monorepos, use per-directory gitignore files to keep each package's rules close to its code. Finally, re-audit twice a year: stacks evolve, build tools change their output folders, and a rule that was essential in 2024 may be dead weight today.
IgnorePilot exists to make all of this frictionless: compose in the left pane, prove in the right pane, decode any pattern in plain English below, then copy or download your .gitignore and get back to building. Your repository's gatekeeper deserves five careful minutes — this page gives you the tools to spend them well.
Frequently asked questions
Is IgnorePilot free, and do I need an account?▾
Yes, IgnorePilot is completely free with unlimited usage. There is no signup, no account, no paywall and no watermark. Everything runs in your browser: the template composer, the gitignore pattern matcher and the check-ignore simulator never send your data anywhere.
How does the git check-ignore simulator work?▾
Paste your .gitignore rules, type a file path such as build/output/app.js, and press Check. IgnorePilot evaluates every pattern in order, shows which patterns matched the path and which did not, and applies git's last-match-wins rule to give an IGNORED or NOT IGNORED verdict — the same logic as the real git check-ignore command. It even warns you when a re-include is blocked because a parent directory is ignored.
What does a ! negation rule do in .gitignore?▾
A pattern starting with ! re-includes a file that an earlier rule ignored. For example, *.log followed by !keep.log ignores every log file except keep.log. The catch: git cannot re-include a file if one of its parent directories is itself ignored, so build/ followed by !build/keep.js still leaves keep.js ignored.
What is the difference between build/ and build in .gitignore?▾
The trailing slash means directories only. build/ ignores a directory named build and everything inside it, at any depth — but never a file named build. Without the slash, build matches both files and directories named build. A leading slash like /build anchors the pattern to the repository root.
Can I combine templates for several stacks, like Node.js and Python?▾
Yes — that is exactly what IgnorePilot's composer is for. Tick any of the 16 stack templates (Node.js, Python, Java, Go, Rust, Ruby, PHP, .NET, Swift, Android, Flutter, Terraform, WordPress, LaTeX, Jupyter, C/C++), add your own custom rules, and IgnorePilot merges everything into one .gitignore, automatically removing duplicate lines. Copy the result or download it as a .gitignore file.
Does IgnorePilot upload my .gitignore or file paths anywhere?▾
No. All matching, merging and explanation happens locally in your browser with plain JavaScript. Your rules and the paths you test never leave your device, so you can safely simulate ignore rules for private or work repositories.