gitgitignoredeveloperversion control

What Belongs in Your .gitignore File

A practical guide to writing and generating .gitignore files that keep secrets, build artifacts, and OS junk out of your repository.

5 min read

Related Tool

.gitignore Generator

Open tool

What Is .gitignore?

A .gitignore file tells Git which files and directories to exclude from version control. Files listed in .gitignore are not staged, committed, or pushed -- they exist only on the local machine. This keeps repositories clean, prevents secrets from leaking into history, and avoids committing files that differ per developer or per machine.

Why It Matters

Committing the wrong files causes real problems. Build artifacts bloat the repository size over time. Dependency folders like node_modules or vendor add thousands of files that are already reproducible from a manifest file. IDE settings files cause constant conflicts when different team members use different editors. And secrets -- API keys, database passwords, private keys -- committed by accident can never be fully removed from Git history without rewriting it.

What to Always Ignore

Dependency directories: node_modules, vendor, .venv, __pycache__, and similar directories should never be committed. They are reproducible by running the install command (npm install, pip install, composer install). Include the lock file (package-lock.json, poetry.lock, composer.lock) but not the installed packages.

Build output: Directories like dist, build, out, and target contain compiled or bundled output. These files are generated from source and should be reproduced by the CI/CD pipeline.

Environment files: .env and its variants (.env.local, .env.production) contain environment-specific configuration, often including secrets. Always gitignore them. Use a .env.example file with placeholder values to document what variables are required.

Editor and IDE metadata: .vscode, .idea, *.suo, *.user, and similar files store per-developer preferences. Including them causes irrelevant conflicts and exposes personal tooling choices.

OS-generated files: .DS_Store (macOS), Thumbs.db (Windows), and desktop.ini are filesystem metadata that belong to the local operating system, not the project.

Log files: *.log files should typically be ignored, though in some cases structured log outputs are part of the committed project.

Patterns and Syntax

Lines starting with # are comments. A pattern with a trailing slash matches only directories. A pattern with a leading slash is anchored to the repository root. An exclamation mark negates a pattern, re-including something a previous rule excluded.

The glob * matches any sequence of characters except a slash. The double glob ** matches across directory boundaries. So logs/ ignores any directory named logs at any depth, while /logs/ ignores only the root-level logs directory.

Global vs Project .gitignore

Each repository has its own .gitignore file. You can also create a global gitignore (git config --global core.excludesFile path/to/global.gitignore) for patterns that apply across all your repositories, typically OS and editor files.

Put OS-specific ignores in the global file so they do not pollute the project .gitignore. Put project-specific ignores in the repository file so all team members share the same rules.

Already Tracked Files

.gitignore only works on untracked files. If a file is already committed, adding it to .gitignore does not stop Git from tracking changes to it. You need to untrack it first with git rm --cached filename, then commit the removal. After that, the file stays on disk but Git ignores future changes.

Generating a .gitignore

Writing a .gitignore from scratch is tedious because each language, framework, and editor has its own set of files to exclude. Generators produce a comprehensive .gitignore by combining well-maintained templates for each technology in your stack.

When starting a project using Node.js, React, VS Code on macOS, a good .gitignore covers: node_modules, dist, .env, .next, .DS_Store, .vscode user settings, and more. Selecting multiple templates merges them into a single file with clear section headers.

Keeping It Updated

As a project grows, new tools, build steps, or team members may introduce new file types. Revisit the .gitignore when adding a new framework, changing the CI/CD pipeline, or onboarding a tool that generates local state files. A clean repository history pays dividends when debugging, auditing, or reviewing history.