Skip to content
Go back

.gitignore Entries Every Project Actually Needs

By SumGuy 4 min read
.gitignore Entries Every Project Actually Needs

The Problem

You committed .env last week. Your database credentials are in git history. Good luck removing that.

Or you pushed node_modules/. Or your macOS .DS_Store files. Or IDE config that breaks other developers’ workflows.

A proper .gitignore prevents 99% of this disaster. Most projects wing it. Don’t.

The Core Entries

Start with these. Add project-specific ones as you go.

# Environment files (ALWAYS)
.env
.env.local
.env.*.local
.env.d.ts
# OS garbage
.DS_Store
Thumbs.db
.vscode/settings.json
.idea/
*.swp
*.swo
*~
.vscode/
# Dependencies
node_modules/
/vendor/
.venv/
env/
venv/
__pycache__/
*.egg-info/
dist/
build/
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pids/
*.pid
# Test coverage
coverage/
.nyc_output/
# Build artifacts
dist/
out/
.next/
.nuxt/
.cache/
.parcel-cache/
.eslintcache
# IDE/Editor config (team-specific, not committed)
.vscode/
.idea/
*.sublime-workspace
*.iml
# OS-specific
.DS_Store
.DS_Store?
._*
.AppleDouble
.LSOverride

Language-Specific Additions

Node.js/JavaScript

node_modules/
npm-debug.log
yarn-error.log
.npm/
package-lock.json # optional: if you want strict versioning
pnpm-lock.yaml # optional: if using pnpm

Python

__pycache__/
*.py[cod]
*$py.class
*.so
.venv/
env/
venv/
ENV/
.pytest_cache/
.coverage
htmlcov/
dist/
build/
*.egg-info/

Go

# Go binaries
*.exe
*.exe~
*.dll
*.so
*.dylib
/bin/
# Go test output
*.test
*.out
.coverage.out

Java

target/
.classpath
.project
.settings/
*.iml
*.class
.gradle/
build/

The “Oops” Categories

Secrets (The Dangerous Ones)

# Credentials
.env
.env.local
.credentials
credentials.json
keyfile.json
private_key.pem
id_rsa
id_rsa.pub

People will tell you “just don’t commit secrets.” Great advice. But humans are lazy. .gitignore is your guardrail.

Generated Files (The Wasteful Ones)

# Generated code
generated/
*_pb2.py # protobuf
*.generated.ts
output/

Never commit generated files. They bloat history and cause merge conflicts. Regenerate from source.

Build Output (The Confusing Ones)

dist/
build/
out/
.build/
target/
*.min.js
*.min.css

Build output is environment-specific. A binary compiled on macOS won’t work on Linux. Regenerate per environment.

Pro Tips

Use a Global .gitignore

OS junk (.DS_Store, .vscode/) isn’t project-specific. Instead:

Terminal window
git config --global core.excludesfile ~/.gitignore_global

Then put OS stuff in ~/.gitignore_global. One-time setup, applies everywhere.

Check What You’re About to Commit

Before git commit, run:

Terminal window
git diff --cached --name-only

See a .env file? Don’t commit. Use git reset HEAD <file> to unstage it.

If You Already Committed Secrets

Panic is optional. Use git filter-repo:

Terminal window
git filter-repo --path .env --invert-paths

This rewrites history and removes .env from all commits. Then force-push (if you can):

Terminal window
git push --force-with-lease

But seriously: don’t let it happen. A good .gitignore is cheaper than an emergency incident response.

Use a Template

GitHub’s .gitignore templates are solid:

Terminal window
curl -s https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore > .gitignore

Copy-paste as a starting point. Customize from there.

Common Mistakes

Mistake 1: Committing .vscode/settings.json. Fix: .vscode/settings.json in .gitignore. (Commit .vscode/extensions.json and .vscode/launch.json if you want — those are team-wide.)

Mistake 2: Ignoring package-lock.json. Fix: DON’T ignore it. Commit package-lock.json so everyone runs the same dependency versions.

Mistake 3: Creating a .gitignore in every subdirectory. Fix: One .gitignore at root. Use paths: src/**/*.log.

Debugging Your .gitignore

Sometimes files still show up even though you think you ignored them. Debug it:

Terminal window
# Check why a specific file is or isn't ignored
git check-ignore -v path/to/file.txt
# List all ignored files
git ls-files --ignored --exclude-standard
# See what git thinks about a file (tracked, untracked, ignored)
git status --short path/to/file.txt

If git check-ignore returns nothing, the file is being tracked (committed already). You can’t ignore an already-tracked file without removing it from the index:

Terminal window
# Remove from git tracking but keep the file locally
git rm --cached .env
echo ".env" >> .gitignore
git commit -m "stop tracking .env"

This is the move when you committed something by accident before adding it to .gitignore.

Negation Patterns

You can un-ignore a specific file after a broad ignore:

# Ignore all .log files
*.log
# Except this one (it's important)
!important.log

Order matters. The last matching rule wins. Negation only works if the parent directory isn’t ignored — you can’t un-ignore a file inside an ignored directory.

.git/info/exclude

There’s a per-repo ignore file that’s never committed: .git/info/exclude. Use it for personal ignores that aren’t team-wide:

Terminal window
echo "my-personal-notes.txt" >> .git/info/exclude

Your personal temp files, local debug scripts, whatever. Gone from git status but never shows up in the shared .gitignore.

The Rule

If it’s generated, secrets, or OS-specific: ignore it. If it’s source code or config the team needs: commit it.

When in doubt, leave it out of git. Your CI/CD pipeline will regenerate it anyway.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it may appear here.


Previous Post
Certificate Pinning: The Nuclear Option for TLS Security (Use With Caution)
Next Post
Multi-Stage Docker Builds: Stop Shipping Your node_modules to Production

Related Posts