Gitignore & Git Attributes

Difficulty: Beginner

Question

How does .gitignore work? What is .gitattributes and when would you use it?

Answer

.gitignore tells Git which files and directories to ignore. Patterns in this file prevent untracked files from being added to the repository. It uses glob patterns: * matches anything, matches directories recursively, ! negates a pattern, and / anchors to the directory containing the .gitignore.

Important: .gitignore only affects untracked files. If a file is already tracked by Git, adding it to .gitignore will not stop Git from tracking it. You must first remove it from tracking with git rm --cached.

.gitattributes controls how Git handles files. It defines per-path attributes like line ending normalization (text=auto), diff and merge strategies for specific file types, and Git LFS (Large File Storage) tracking for binary files. It ensures consistent behavior across different operating systems and editors.

Common .gitattributes uses: ensuring LF line endings on all platforms, marking binary files so Git does not try to diff them, and configuring Git LFS for large assets like images and videos.

Code examples

.gitignore Patterns

# .gitignore for a Node.js project

# Dependencies
node_modules/

# Build output
dist/
build/
*.js.map

# Environment files (NEVER commit secrets)
.env
.env.local
.env.*.local

# OS files
.DS_Store
Thumbs.db

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

# Logs
*.log
logs/

# Coverage
coverage/

# Pattern examples:
# *        matches anything except /
#        matches directories recursively
# ?        matches any single character
# [abc]    matches a, b, or c
# !        negates (un-ignore)

# Ignore all .log files except error.log
*.log
!error.log

# Ignore build/ in root only (not subdir/build/)
/build/

# Ignore all files in temp directories
/temp/

Start with a template from github.com/github/gitignore for your language. Always ignore node_modules, .env, and build output. The ! operator lets you whitelist specific files.

Removing Already-Tracked Files

# Problem: you committed .env before adding it to .gitignore
# .gitignore does NOT stop tracking already-tracked files

# Solution: remove from Git but keep the file locally
git rm --cached .env
git commit -m "chore: stop tracking .env file"

# Remove a directory from tracking
git rm -r --cached node_modules/
git commit -m "chore: remove tracked node_modules"

# Remove all files that should be ignored
# (based on current .gitignore)
git rm -r --cached .
git add .
git commit -m "chore: apply gitignore to all tracked files"

# Check what Git is ignoring
git status --ignored

# Check why a file is ignored
git check-ignore -v path/to/file
# .gitignore:3:*.log    path/to/file
# Shows which rule and which .gitignore file matched

# Global gitignore (for personal OS/IDE files)
git config --global core.excludesFile ~/.gitignore_global

git rm --cached removes from tracking without deleting the file. Use a global gitignore for OS-specific files so project .gitignore stays clean.

.gitattributes Configuration

# .gitattributes - normalize line endings
* text=auto
*.js text eol=lf
*.ts text eol=lf
*.json text eol=lf
*.md text eol=lf
*.sh text eol=lf

# Mark binary files (don't diff or merge)
*.png binary
*.jpg binary
*.pdf binary
*.woff2 binary

# Git LFS for large files
*.psd filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text

# Custom diff for certain files
*.lock linguist-generated=true
*.min.js linguist-vendored=true

# Setup Git LFS
git lfs install
git lfs track "*.psd"
git lfs track "*.mp4"
# This updates .gitattributes automatically

# Check LFS tracked files
git lfs ls-files

text=auto normalizes line endings across platforms. binary prevents meaningless diffs on images. Git LFS stores large files efficiently on a separate server.

Key points

Concepts covered

.gitignore, .gitattributes, Ignoring Files, Line Endings, LFS