Understanding .gitignore files
Version control repositories should only contain human-authored source code, build manifests,
and required documentation. Generated binaries, external dependency packages (such as
node_modules), runtime log files, and OS thumbnails clutter Git commit histories
and slow down cloning speeds.
A .gitignore text file placed in your repository root tells Git which files and
directory paths to exclude from indexing. Patterns use standard globbing syntax, matching
filenames, wildcards, and directory trees recursively.
Essential pattern rules
Git resolves ignore patterns using straightforward rules:
-
Trailing slashes: A trailing slash (
build/) matches directories only. Without the slash, Git ignores both directories and files sharing that name. -
Asterisk wildcards: An asterisk (
*.log) matches any characters except directory separators, capturing all log files in a single folder. -
Double asterisk (globstar): A double asterisk (
**/logs) matches directories across arbitrary nesting depths. -
Negation: An exclamation mark prefix (
!important.log) re-includes a file that was previously excluded by an earlier rule.
Worked examples
-
Full-stack Node.js project: Ignoring
node_modules/, compilation artifacts (dist/), and environment secrets (.env*). -
Python service: Excluding compiled bytecode (
__pycache__/,*.pyc) and local virtual environments (venv/,.venv/). -
Cross-platform team: Filtering operating system metadata like macOS
.DS_Storeand WindowsThumbs.dbalongside IDE directories like.idea/and.vscode/.
Common mistakes
-
Adding already tracked files: Adding a file to
.gitignoreafter committing it has no effect. Rungit rm --cachedto stop tracking it. -
Negating files inside an ignored folder: If a parent directory is excluded (
cache/), Git will not re-include a nested child file (!cache/keep.txt). You must negate the parent folder first. -
Committing production secrets: Never rely on memory to ignore secrets; ensure
all sensitive credentials files are defined in
.gitignorebefore your initial commit.
Frequently asked questions
What does a .gitignore file do in a Git repository?
A .gitignore file specifies intentionally untracked patterns that Git should ignore. Files matching these patterns are not indexed, preventing build artifacts, temporary caches, and secret credentials from being committed.
Does .gitignore affect files already tracked in Git history?
No. If a file was already committed to Git, adding it to .gitignore does not untrack it. You must run "git rm --cached <file>" to remove it from Git tracking while preserving the local copy on disk.
How do I ignore an entire directory except for one specific file?
Use negation patterns with an exclamation mark. For example: "dist/*" followed by "!dist/bundle.js" tells Git to ignore all files in dist except bundle.js.
What is a global gitignore versus a repository .gitignore?
A repository .gitignore lives in the project root and is shared with team members. A global gitignore (configured via core.excludesFile) applies only to your local machine, ideal for personal editor artifacts like .DS_Store or local vim swap files.
Why should .env files always be included in .gitignore?
Environment files typically contain private API keys, database connection strings, and tokens. Committing .env files to public or shared repositories is a major source of security breaches.