.gitignore
.gitignore: keep files out of version control. Globs, negation, scoping per-directory, and the patterns every project needs.
Git — .gitignore
EXAMPLE
# ===== Basic syntax ===== # Comments start with # # Blank lines are ignored # One pattern per line # Match a file: secrets.json # Match anywhere: *.log # Match a directory (trailing slash): node_modules/ # Match anywhere in tree: **/*.log # Anchor to root (leading slash): /build/ # only ./build, not src/build # Negate (un-ignore): *.log !important.log # include this one anyway # ===== Glob patterns ===== *.tmp # any .tmp *[Cc]ache* # match Cache or cache **/temp/** # any 'temp' folder at any depth [abc].txt # a.txt or b.txt or c.txt ?ar # bar, car, ear, ... # ===== Per-directory .gitignore ===== # Each directory can have its own .gitignore. # Inner rules override outer rules. # src/.gitignore: *.local.ts # ===== Common patterns ===== # Node: node_modules/ .npm/ .yarn/ .pnpm-store/ dist/ build/ coverage/ *.log .env .env.* !.env.example # Python: __pycache__/ *.pyc *.pyo .venv/ venv/ .pytest_cache/ .coverage *.egg-info/ build/ dist/ # Java / Maven / Gradle: target/ build/ *.class .gradle/ .idea/ *.iml # macOS / IDE / OS: .DS_Store Thumbs.db .vscode/ !.vscode/extensions.json !.vscode/settings.json .idea/ *.swp *.swo # ===== Global gitignore (per user) ===== git config --global core.excludesfile ~/.gitignore_global # Add OS / editor files there so every project gets them without explicit listing. # ===== Already-tracked files ===== # .gitignore does NOT affect files already tracked. # To untrack a file but keep it locally: git rm --cached secret.json git commit -m 'untrack secret.json' # Then add to .gitignore. # ===== Force-add an ignored file ===== git add -f forced-file.log # ===== Check what is ignored / why ===== git check-ignore -v dist/main.js # .gitignore:5:dist/ dist/main.js git status --ignored # ===== Templates ===== # GitHub provides good templates: github.com/github/gitignore # Toptal has gitignore.io for combined .gitignore generation. # ===== Patterns to internalise ===== # - .env in .gitignore; .env.example committed # - node_modules / build / dist / coverage / .DS_Store etc. # - Commit a base .gitignore on day 1; iterate # - Use git check-ignore when surprised # ===== Pitfalls ===== # - Committing .env, then 'gitignoring' it (still in history; rotate secrets!) # - Forgetting trailing slash on directories -> partial match # - Negation on a file inside an ignored dir -> doesn't work (parent rule wins) # - Editor files (.idea, .vscode) without selective inclusion -> teammates fight
Why it matters
A solid .gitignore on day one prevents most accidental commits. Use a template for the stack, add .env (and rotate any leaked secrets), and reach for git check-ignore when surprised. Negate within visible scopes only — parent rules cannot be undone by children.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Discussion
Loading…