What a .gitignore file does
A .gitignore file tells Git which files and directories to leave out of version control. It doesn't hide files from your filesystem or from other tools — it only affects git status, git add, and git commit. Anything matching a pattern in .gitignore is skipped when Git decides what's "untracked."
The file itself is just plain text, one pattern per line, placed at the root of your repository (or in any subdirectory, where its rules apply from that point down). Git reads it automatically — there's nothing to configure.
Why it matters
Without a .gitignore, three categories of files routinely end up committed by accident:
- Build output —
dist/,build/, compiled binaries — regeneratable, and bloats the repo with every rebuild. - Dependencies —
node_modules/,vendor/— can be thousands of files and is reinstallable from a lockfile. - Secrets and local config —
.env, API keys, IDE workspace settings — the most damaging category, since a committed secret stays in Git history even after you delete it later.
Pattern syntax, with examples
The rules are simple but have a few sharp edges worth knowing:
node_modules/— the trailing slash matches only directories, not a file namednode_modules.*.log— the asterisk matches any characters within one path segment. Matchesdebug.log, notlogs/debug.log.**/*.log— the double-asterisk matches across directory boundaries, so this catches.logfiles at any depth./config.json— a leading slash anchors the pattern to the directory containing the.gitignorefile, rather than matching aconfig.jsonanywhere in the tree.!important.log— a leading!negates a pattern, re-including a file that a broader rule above it excluded. Order matters: you can't re-include something inside an already-ignored directory.# comment— lines starting with#are comments and ignored by Git.
"I added it to .gitignore, but Git is still tracking it"
This is the single most common .gitignore problem, and it happens because .gitignore only affects untracked files. If a file was already committed before you added the rule, Git keeps tracking it regardless of what the pattern says. To fix it, remove the file from Git's index without deleting it from disk:
git rm --cached path/to/file
git commit -m "Stop tracking path/to/file"For an entire directory that should never have been committed (a classic case: node_modules/ got pushed before anyone added a .gitignore), the same idea applies recursively:
git rm -r --cached node_modules
git commit -m "Remove node_modules from version control"Note that this doesn't remove the file from your Git history — anyone who clones the repo can still find it in an old commit. If a real secret was committed, rotate the credential; removing it from history afterward (via tools like git filter-repo) is a separate, more involved step.
One file per stack, or combine them?
Most real projects need more than one template — a Node.js backend developed in VS Code on a Mac needs the Node, VS Code, and macOS rules simultaneously (build artifacts, editor settings, and .DS_Store respectively). GitHub's own template collection ships these as separate files for exactly this reason — you're expected to combine the ones relevant to your setup into a single .gitignore.