.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 orderimportant.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:

Rulesbuild/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:

RulePathResultWhy
*.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

  1. Select the languages and tools your project uses.
  2. Review the generated patterns.
  3. Save it as .gitignore at your repository root.
  4. 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.