.gitignore Generator
Build a .gitignore file by picking your languages, frameworks and tools — plus the reason ignoring a file does not remove it.
Pick every language, editor, and OS your project uses:
A .gitignore does not untrack anything
The most expensive misunderstanding first, because no pattern on this page fixes it. .gitignore applies only to files git is not already tracking. Add a file, commit it, then add it to .gitignore, and git carries on tracking it exactly as before — the ignore rules are never consulted for something already in the index.
This is why "I added it to .gitignore" is not a fix for a committed credential. The file keeps
being tracked, and every previous version stays in the history whatever you do next. Untracking
it takes git rm --cached, and removing it from the history takes a rewrite of every
commit that touched it. If a secret was ever pushed, treat it as disclosed and rotate it — that
is cheaper and more reliable than any amount of history surgery.
The last matching rule wins, so order is meaningful
Rules are applied in file order and the last one to match decides. That makes two adjacent lines order-dependent in a way nothing in the syntax hints at:
| Rules, in order | important.log |
|---|---|
*.log</code><br /><code>!important.log | tracked |
!important.log</code><br /><code>*.log | ignored |
The same two lines, reordered, give opposite answers. Since generated additions tend to get appended at the bottom, a rule added later can silently override an exception written near the top — and it will not look like it did anything.
And you cannot rescue a file from inside an ignored directory
This is the one that produces the most confused bug reports, and it looks like it ought to work:
| Rules | build/keep.txt | |
|---|---|---|
build/</code><br /><code>!build/keep.txt | ignored | the negation does nothing |
build/*</code><br /><code>!build/keep.txt | tracked | the documented workaround |
Git does not descend into an excluded directory, so it never sees keep.txt to
re-include it. The negation is not overridden — it is never evaluated at all. Excluding the
directory's contents instead leaves git walking the directory, and then the exception
applies. The difference is one character.
The remaining patterns behave more predictably once you know that a slash anywhere in a rule anchors it:
| Rule | Path | Result | Why |
|---|---|---|---|
*.log | logs/app.log | ignored | no slash, so it matches at any depth |
/*.log | logs/app.log | tracked | a leading slash anchors it to the root |
/*.log | app.log | ignored | and matches only there |
doc/**/*.pdf | doc/a/b/x.pdf | ignored | a double star spans directories |
doc/*/*.pdf | doc/a/b/x.pdf | tracked | a single star does not cross a slash |
src/index.ts | lib/src/index.ts | tracked | any slash anchors the whole pattern |
Every result in these three tables is computed by a matcher checked against git's documented
behaviour on each build, including the awkward cases above — not transcribed from the
documentation. If you are ever unsure what a rule will do,
git check-ignore -v <path> tells you which line decided, which is faster
than reasoning about it.
How to use
- Select the languages and tools your project uses.
- Review the generated patterns.
- Save it as .gitignore at your repository root.
- Untrack anything already committed — ignoring is not enough.
Frequently asked questions
Why is my file still tracked after adding it to .gitignore?
Because .gitignore only affects untracked files. Anything already committed continues to be tracked regardless, and must be removed from the index explicitly with git rm --cached. This is the single most common gitignore confusion.
What should never be committed?
Credentials of any kind, environment files containing secrets, build output, dependency directories, and editor and OS clutter. Secrets are the serious one — once committed they are in the history, and removing them means rewriting it and rotating the credential anyway.
How do I ignore everything except a few files?
Ignore everything with an asterisk, then negate the exceptions with a leading exclamation mark. The catch is that a file cannot be re-included if its parent directory is excluded, so the directory has to be unignored first — which is why these patterns are fiddly.
What is the difference between .gitignore and .git/info/exclude?
Scope. A .gitignore is committed and applies to everyone working on the repository; the exclude file is local and private. Personal editor preferences belong in the local one or in a global gitignore rather than being imposed on the whole team.
Does a trailing slash matter?
Yes — it restricts the pattern to directories. Without it, a pattern matches both files and directories of that name. It is worth adding when you mean a directory, since it prevents an unexpected file match.
Can I have more than one gitignore file?
Yes. Rules can live in any directory and apply from there downward, which is useful in a monorepo where subprojects have different needs. Rules in deeper directories take precedence, and a global gitignore in your home directory covers your own tooling across every repository.
🔒 This tool runs entirely in your browser. Nothing you enter is uploaded, logged, or stored.