What to Put in .gitignore (and Why)
June 5, 2026 · 3 min read
A .gitignore file tells Git which files and directories to leave untracked. Getting it wrong means committing files that shouldn't be in the repository — credentials, build output, editor config, OS artefacts — or spending time on merge conflicts in files nobody should have committed in the first place.
What to always ignore
Dependency folders
Never commit installed dependencies. They can always be restored from your lock file and are often OS-specific or architecture-specific:
node_modules/ # Node.js
vendor/ # Go, PHP (Composer)
venv/ / .venv/ # Python virtualenv
target/ # Rust / Maven
Build output
Compiled and generated output is reproducible from source. Committing it bloats the repository and causes constant noise in diffs:
dist/
build/
out/
*.class # Java
*.o # C/C++ object files
Environment files
Environment files contain secrets (API keys, database passwords). They must never enter version control:
.env
.env.local
.env.*.local
If you need to document which environment variables are required, commit a .env.example file with placeholder values and add .env (but not .env.example) to .gitignore.
OS artefacts
macOS creates .DS_Store in every directory it touches. Windows creates Thumbs.db. These are OS-specific and meaningless to other developers:
.DS_Store # macOS
Thumbs.db # Windows
Desktop.ini # Windows
Editor / IDE files
Editor config files that are personal preferences (keybindings, workspace layout) should not be shared:
.idea/ # JetBrains IDEs
*.suo / *.user # Visual Studio
.vscode/ # VS Code (workspace-specific settings)
Note: if your team has agreed on shared VS Code settings (recommended extensions, formatter config), it is fine to commit .vscode/settings.json and .vscode/extensions.json while still ignoring .vscode/ — use negation patterns to opt specific files back in:
.vscode/
!.vscode/settings.json
!.vscode/extensions.json
.gitignore pattern syntax
| Pattern | Meaning |
|---|---|
*.log |
All .log files in any directory |
build/ |
The build directory (trailing / = directory only) |
/dist |
Only dist at the repo root (leading / = anchored) |
!keep.log |
Re-include keep.log even if *.log ignores it |
**/*.snap |
Any .snap file at any depth |
doc/**/*.txt |
All .txt files inside doc/ |
Rules are processed top-to-bottom. A negation (!) only un-ignores a file if its parent directory is not itself ignored — so !node_modules/keep.txt has no effect if node_modules/ is ignored.
Combining stacks
Most projects span multiple stacks. A Next.js project on macOS, built in VS Code, should combine the Next.js, Node.js, macOS, and VS Code sections — there is no reason to pick just one. The .gitignore Generator lets you tick any combination of tech stacks and generates the merged file instantly.
What not to ignore
- Lock files (
package-lock.json,yarn.lock,Cargo.lock,poetry.lock). These pin exact dependency versions and ensure reproducible installs. They belong in version control. - Config files (
tsconfig.json,eslint.config.js,.prettierrc). These define project-wide rules and should be shared. - Migration files and schema definitions — they are history and should not be lost.
The global gitignore
You can define a personal global .gitignore for OS and editor artefacts so you don't have to add them to every project. Set it up once:
git config --global core.excludesfile ~/.gitignore_global
Then put macOS, Windows, and your editor entries in ~/.gitignore_global. The project-level .gitignore can then focus on language and framework specifics.
Checking what is being ignored
To see which files Git is currently ignoring:
git status --ignored
git check-ignore -v path/to/file # explain why a specific file is ignored
If you have already committed a file that should be ignored, add it to .gitignore and then run:
git rm --cached path/to/file
This removes it from tracking without deleting it from disk. Commit the change and it will no longer appear in future diffs.