Skip to main content
The .gitignore file specifies intentionally untracked files that Git should ignore. Files already tracked by Git are not affected.

Overview

A .gitignore file tells Git which files (or patterns) to ignore. This is useful for:
  • Build artifacts and generated files
  • Dependencies and packages
  • IDE and editor configuration
  • Operating system files
  • Temporary files and caches
  • Sensitive data like credentials

File Locations

Git checks for ignore patterns in multiple locations:

Repository .gitignore

Location: Root or any directory in the repository Use for: Files that all developers should ignore (build output, dependencies)
# Create repository .gitignore
touch .gitignore
git add .gitignore
git commit -m "Add .gitignore"

Per-Repository Exclude

Location: .git/info/exclude Use for: Files specific to your workflow that shouldn’t be shared
# Edit local exclude file
vim .git/info/exclude

Global Ignore

Location: Configured via core.excludesFile Use for: Files to ignore across all repositories (OS files, editor config)
# Set up global gitignore
git config --global core.excludesFile ~/.gitignore_global

Pattern Format

Basic Patterns

# Ignore all .log files
*.log

# Ignore the build directory
build/

# Ignore specific file
config.local.js

# Ignore all .txt files in doc/ directory
doc/*.txt

Pattern Rules

# This is a comment

# Blank lines are ignored
*.log
  • Blank lines are ignored (can separate groups for readability)
  • Lines starting with # are comments
  • Use \# to match files starting with #
# * matches anything except /
*.log

# ? matches any one character
?.txt

# [abc] matches any character in brackets
[Tt]emp

# [a-z] matches any character in range
[0-9].txt
  • * matches zero or more characters (except /)
  • ? matches exactly one character
  • [abc] matches any character in the set
  • [0-9] matches any character in the range
# Ignore foo/bar directory anywhere
foo/bar/

# Ignore only in root
/foo

# Ignore doc/notes.txt but not doc/server/notes.txt
doc/*.txt
  • / at the start matches from repository root
  • / at the end matches only directories
  • / in the middle anchors the pattern to that level
# Ignore all .log files
*.log

# But track important.log
!important.log

# Ignore all files in build/
build/*

# But track build/.gitkeep
!build/.gitkeep
  • ! negates a pattern (re-includes files)
  • Cannot re-include a file if parent directory is excluded
  • Prefix with \! to match files starting with !
# Match foo anywhere
**/foo

# Match everything inside abc/
abc/**

# Match zero or more directories
a/**/b
  • **/ at start matches in all directories
  • /** at end matches everything inside
  • /**/ in middle matches zero or more directories

Common Patterns

Node.js Project

# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Production build
build/
dist/

# Environment variables
.env
.env.local
.env.*.local

# IDE
.vscode/
.idea/
*.swp
*.swo

# OS files
.DS_Store
Thumbs.db

# Testing
coverage/
.nyc_output/

# Logs
logs/
*.log

Python Project

# Byte-compiled files
__pycache__/
*.py[cod]
*$py.class

# Virtual environments
venv/
env/
ENV/
.venv/

# Distribution / packaging
build/
dist/
*.egg-info/

# Testing
.pytest_cache/
.coverage
htmlcov/

# IDE
.vscode/
.idea/
*.swp

# Environment
.env

# Jupyter Notebook
.ipynb_checkpoints/

Java Project

# Compiled class files
*.class

# Package Files
*.jar
*.war
*.ear
*.zip
*.tar.gz

# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup

# Gradle
.gradle/
build/

# IDE
.idea/
*.iml
.classpath
.project
.settings/

# OS
.DS_Store

macOS

# macOS system files
.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

# Files that might appear in the root
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns

Windows

# Windows thumbnail cache
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin
$RECYCLE.BIN/

# Windows shortcuts
*.lnk

IDE and Editors

# VS Code
.vscode/
*.code-workspace

# JetBrains IDEs
.idea/
*.iml
*.iws
*.ipr

# Vim
*.swp
*.swo
*~

# Emacs
*~
\#*\#
.\#*

# Sublime Text
*.sublime-project
*.sublime-workspace

Examples

Ignore Everything Except Specific Files

# Ignore everything
/*

# But keep these files
!.gitignore
!README.md
!src/

Ignore Everything in a Directory Except One Subdirectory

# Ignore everything in foo/
foo/*

# But keep foo/bar/
!foo/bar/

Ignore Files Only at Root

# Ignore config.json at root only
/config.json

# This would ignore config.json anywhere:
# config.json

Pattern Matching Examples

# hello.* matches hello.txt, hello.c, hello.java
hello.*

# /hello.* matches only at root
/hello.*

# foo/ matches foo directory anywhere
foo/

# foo/* matches files inside foo, not foo/bar/baz.txt
foo/*

# foo/** matches everything inside foo recursively
foo/**

# **/foo matches foo anywhere
**/foo

# a/**/b matches a/b, a/x/b, a/x/y/b
a/**/b

Working with .gitignore

Check if a File is Ignored

git check-ignore -v file.txt
Output shows which rule is ignoring the file:
.gitignore:3:*.txt    file.txt

Check Multiple Files

git check-ignore file1.txt file2.log dir/

Debug Ignore Patterns

# Show all ignored files
git status --ignored

# List ignored files
git ls-files --ignored --exclude-standard

Stop Tracking Already Tracked Files

If you add a pattern to .gitignore but the file is already tracked:
# Remove from index but keep in working directory
git rm --cached file.txt

# Remove directory
git rm -r --cached directory/

# Commit the change
git commit -m "Stop tracking file.txt"

Remove All Ignored Files

This permanently deletes files! Use with caution.
# Preview what will be deleted
git clean -ndX

# Delete ignored files
git clean -fdX

Global .gitignore Setup

Create Global Ignore File

# Create the file
touch ~/.gitignore_global

# Configure Git to use it
git config --global core.excludesFile ~/.gitignore_global
# OS Files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Thumbs.db
Desktop.ini

# Editor files
*~
*.swp
*.swo
.vscode/
.idea/
*.sublime-workspace

# Compiled files
*.com
*.class
*.dll
*.exe
*.o
*.so

# Archives
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip

Best Practices

Commit .gitignore

Always commit .gitignore to share ignore patterns with your team

Ignore Early

Add patterns before creating files to avoid accidentally committing them

Use Global for Personal Files

Keep editor and OS-specific ignores in global .gitignore

Use Comments

Document why files are ignored, especially non-obvious patterns

Don’t Ignore

  • .gitignore itself
  • Configuration templates (e.g., config.example.js)
  • Empty directory placeholders (.gitkeep)
  • Lock files (package-lock.json, Gemfile.lock)

Always Ignore

  • Secrets and credentials
  • API keys and tokens
  • Database files
  • Build artifacts
  • Dependencies (node_modules, vendor)
  • Generated files

Templates

GitHub maintains a collection of useful .gitignore templates: Visit github/gitignore for more templates.

Troubleshooting

File Still Being Tracked

Problem: Added pattern to .gitignore but file still appears in git status Solution: The file was already tracked. Remove it from the index:
git rm --cached filename
git commit -m "Stop tracking filename"

Pattern Not Working

Problem: Pattern doesn’t match expected files Solution: Use git check-ignore to debug:
# Test specific file
git check-ignore -v path/to/file

# No output means file is not ignored

Cannot Re-include File in Ignored Directory

Problem: Trying to track a file inside an ignored directory Solution: Exclude the directory contents, then re-include specific files:
# Wrong - cannot re-include after ignoring parent
build/
!build/important.txt

# Correct - ignore contents, then re-include
build/*
!build/important.txt

See Also

Build docs developers (and LLMs) love