Skip to content

.gitignore Explained: Patterns, Pitfalls and a Generator

Every developer has committed node_modules, a .DS_Store, or — worse — a .env file at least once. The fix is a good .gitignore created before the first commit, and a working understanding of the three or four pattern rules that cover 99% of cases. This guide explains the syntax, the classic "but I added it to .gitignore!" trap, and how to use the generator.

Open the .gitignore Generator →
Screenshot of the .gitignore Generator tool on andergrove.com
The .gitignore Generator running in the browser — free, no signup, nothing uploaded.

What the generator does

The .gitignore generator composes a ready-to-commit ignore file from curated blocks: operating-system junk (macOS's .DS_Store, Windows' Thumbs.db), editor metadata (VS Code, JetBrains, Vim, Emacs), build artefacts for twelve languages, framework output folders, and a secrets block (.env, keys, credentials) that most templates forget. Each selection becomes a labelled section, so the file stays readable and easy to prune later.

How do .gitignore patterns work?

A .gitignore is a list of glob patterns, one per line, matched against paths relative to the file's location. Four rules cover almost everything:

PatternMatches
node_modules/A trailing slash means "directories only" — this one, anywhere in the repo
*.log* matches anything except / — every .log file, any directory
/dist/A leading slash anchors to the repo root — dist/ at the top level only
!keep.log! re-includes something a previous pattern excluded

Two more that occasionally matter: ** crosses directory boundaries (docs/**/*.pdf), and # starts a comment. One trap with negation: you cannot re-include a file if its parent directory is excluded — !.vscode/settings.json only works because the template excludes .vscode/* (the contents), not .vscode/ (the directory).

Why is Git still tracking a file I ignored?

Because .gitignore only applies to untracked files. If debug.log was committed last month, adding *.log today changes nothing — Git keeps tracking files it already tracks. The fix is to remove it from the index while keeping your local copy:

git rm -r --cached path/to/file-or-dir
git commit -m "Stop tracking ignored files"

From that commit on, the ignore rule applies. Note the file's history is still in the repository — if what you committed was a secret, removing it from tracking is not enough: rotate the credential, and consider a history rewrite if the repo is shared.

The global gitignore nobody sets up

OS and editor junk (.DS_Store, .idea/, swap files) is a property of your machine, not of any project — which is why seasoned teams keep it out of project .gitignore files and put it in a personal global one instead:

git config --global core.excludesFile ~/.gitignore_global

Put your OS and editor sections there once, and every repository you touch is covered — including other people's, where you can't edit the project file. The generator's OS/editor groups make a good starting point for it. (Including them in project files too does no harm; it protects teammates who haven't set this up.)

Secrets deserve more than an ignore rule

The generator's "Secrets & env files" block (.env, *.pem, *.key, credentials.json) should be in essentially every repository — but treat it as a seatbelt, not a strategy. An ignored .env still ends up in copy-pastes, backups and CI logs, and one git add -f defeats it. Keep an .env.example with dummy values committed (the template re-includes it) so newcomers know what to configure, and rotate anything that ever lands in history.

Ready to try it? Open the .gitignore Generator →

Related guides