.gitignore prevents untracked files from being proposed for addition. It does not stop Git from tracking a file that is already committed. That distinction explains most “why is node_modules still showing up?” reports.
A useful baseline
node_modules/
.next/
dist/
.env
.env.local
*.log
Keep lockfiles such as package-lock.json, pnpm-lock.yaml, or yarn.lock tracked unless the project has a deliberate policy otherwise. They are reproducibility inputs, not build junk.
Patterns are scoped and ordered
| Pattern | Matches | Gotcha |
|---|---|---|
build/ | Any directory named build | Use /build/ for repository root only |
*.log | Log files anywhere | Does not match a directory named logs |
!.env.example | Re-includes an example file | Parent directories must not remain ignored |
Use git check-ignore -v path/to/file to see the exact rule responsible. It is much faster than editing patterns by feel.
Remove an already tracked mistake
git rm -r --cached node_modules
git commit -m "Stop tracking node_modules"
--cached removes files from the index, not from your working directory. Review the staged deletion before committing; it is easy to accidentally target a generated directory the build still expects locally.
Never put a real secret in
.gitignoreand assume it is safe. If it was committed, rotate it and remove it from history according to your repository's incident process.
An ignore file is project documentation: it tells contributors what the repository intentionally owns. Keep it short, specific, and versioned beside the code.
