Not every file in your project should be tracked by Git. Dependencies, build artifacts, system files, and especially sensitive data like API keys should never be committed to version control. The .gitignore file is your guardian against these mistakes. In this lesson, you'll learn how .gitignore works, master ignore patterns and wildcards, protect sensitive information, use templates for different project types, and handle files that were accidentally committed. Proper use of .gitignore keeps repositories clean, secure, and professional!
What Is .gitignore?
.gitignore is a special file that tells Git which files and directories to exclude from version control.
Why Use .gitignore?
- Security: Prevent committing passwords, API keys, secrets
- Cleanliness: Exclude dependencies, build artifacts, logs
- Performance: Smaller repositories, faster operations
- Relevance: Only track source code, not generated files
- Cross-platform: Ignore OS-specific files (.DS_Store, Thumbs.db)
- Editor files: Exclude IDE configurations (.vscode/, .idea/)
What NOT to commit:
- Dependencies (node_modules/, vendor/)
- Build output (dist/, build/, *.exe)
- Environment files (.env, .env.local)
- Secrets (API keys, certificates, passwords)
- Log files (*.log, logs/)
- System files (.DS_Store, Thumbs.db)
- Editor configs (.vscode/, .idea/)
- Temporary files (*.tmp, *.cache)
How .gitignore Works
Files matching patterns in .gitignore are:
- Not shown in
git statusas untracked - Not staged when you run
git add . - Not included in commits
- Still present in your working directory (not deleted)
π .gitignore Is Just a Text File
.gitignore is a simple text file with one pattern per line. You can edit it with any text editor. The dot (.) at the beginning makes it a hidden file on Unix systems.
Creating a .gitignore File
Method 1: Create Manually
# In your repository root
touch .gitignore
# Edit it
nano .gitignore
# or
code .gitignoreMethod 2: Create with Initial Content
# Create with basic Node.js ignores
cat > .gitignore << EOF
node_modules/
.env
*.log
dist/
EOFMethod 3: Use GitHub Templates
When creating a repository on GitHub:
- During repository creation
- Click "Add .gitignore" dropdown
- Choose your language/framework (Node, Python, Java, etc.)
- GitHub adds a pre-configured .gitignore
Method 4: Use gitignore.io
Generate custom .gitignore files at gitignore.io:
- Enter your stack (e.g., "Node, macOS, VSCode")
- Get a comprehensive .gitignore
- Copy to your project
Pro Tip: Commit .gitignore to your repository so everyone on the team uses the same ignore rules!
Pattern Syntax and Rules
Basic Patterns
1. Exact Match
# Ignore specific file
secret.txt
# Ignore specific directory (trailing slash)
logs/
# This ignores:
# - logs/ in root
# - any/path/logs/ anywhere in project2. Wildcards (*)
# Ignore all .log files
*.log
# Ignore all .txt files in any directory
*.txt
# Ignore files starting with 'temp'
temp*
# Ignore files ending with '.backup'
*.backup3. Question Mark (?)
# Matches single character
# Ignores file1.txt, fileA.txt, but not file10.txt
file?.txt4. Character Ranges ([...])
# Ignore file0.txt through file9.txt
file[0-9].txt
# Ignore fileA.txt, fileB.txt, fileC.txt
file[ABC].txt5. Double Asterisk (**)
# Ignore .log files in any subdirectory
**/*.log
# Ignore node_modules anywhere in the tree
**/node_modules/
# Ignore all files in any 'temp' directory
**/temp/*6. Negation (!)
# Ignore all .txt files
*.txt
# But track important.txt
!important.txt
# Ignore all files in logs/
logs/*
# But track logs/keep.log
!logs/keep.log7. Comments (#)
# This is a comment
# Comments help explain why things are ignored
# Dependencies
node_modules/
# Environment variables
.env*
# Build output
dist/
build/Pattern Rules Summary
Pattern | Matches
-----------------|----------------------------------
file.txt | Specific file in root or anywhere
*.log | All .log files
logs/ | Directory named 'logs' anywhere
/logs/ | Only 'logs' in root directory
**/logs/ | 'logs' in any subdirectory
*.log | Any .log file anywhere
**/*.log | .log files in any subdirectory
!important.log | Exception: don't ignore this
file[0-9].txt | file0.txt through file9.txt
temp? | temp1, tempA, etc. (1 character)
#comment | Comment line (ignored by Git)Common .gitignore Patterns
Node.js / JavaScript Projects
# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Build output
dist/
build/
.next/
out/
# Misc
.DS_Store
*.pem
.vscode/
.idea/
# Testing
coverage/
.nyc_output/
# Cache
.cache/
.parcel-cache/
.npm/Python Projects
# Byte-compiled / optimized
__pycache__/
*.py[cod]
*$py.class
# Virtual environments
venv/
env/
ENV/
.venv
# Distribution / packaging
dist/
build/
*.egg-info/
.eggs/
# Unit test / coverage
.pytest_cache/
.coverage
htmlcov/
# Environment variables
.env
*.env
# IDEs
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.dbJava Projects
# Compiled class files
*.class
# Package files
*.jar
*.war
*.ear
# Build directories
target/
build/
out/
# IDE
.idea/
*.iml
.eclipse/
.settings/
# Gradle
.gradle/
gradle-app.setting
# Maven
pom.xml.tag
pom.xml.releaseBackup
# Log files
*.log
# OS
.DS_Store
Thumbs.dbReact / Next.js Specific
# Dependencies
node_modules/
/.pnp
.pnp.js
# Next.js
.next/
out/
next-env.d.ts
# Production
build/
dist/
# Debug
npm-debug.log*
yarn-debug.log*
# Environment
.env*.local
.env
# Vercel
.vercel
# Testing
coverage/
# Misc
.DS_Store
*.pem
.vscode/
.idea/WordPress Projects
# WordPress core files
/wp-admin/
/wp-includes/
/wp-content/uploads/
wp-config.php
# Plugins (track only custom)
/wp-content/plugins/*
!/wp-content/plugins/my-custom-plugin/
# Themes (track only custom)
/wp-content/themes/*
!/wp-content/themes/my-custom-theme/
# Cache
/wp-content/cache/
# Backups
*.sql
*.sql.gz
# Log files
*.logProtecting Sensitive Data
Environment Variables
Never commit files containing secrets:
# Environment files
.env
.env.local
.env.development
.env.production
.env.*.local
# Configuration with secrets
config/secrets.yml
config/database.yml
credentials.json
# API keys
*api-key*
*apikey*
*.key
*.pemCreate Example Files Instead
Provide templates without actual secrets:
# Copy this file to .env and fill in your values
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
API_KEY=your_api_key_here
SECRET_KEY=your_secret_key_here
STRIPE_KEY=sk_test_your_stripe_keyIn .gitignore:
# Ignore actual env file
.env
# But track the example
!.env.exampleπ Security First
Critical Security Rules:
- Never commit passwords, API keys, or tokens
- Never commit database credentials
- Never commit SSL certificates or private keys
- Use environment variables for secrets
- Always add .env to .gitignore BEFORE committing anything
If You Already Committed Secrets
IMPORTANT: If you've already committed secrets:
- Immediately rotate/change the secret (the old one is compromised!)
- Remove it from Git history (see next section)
- Add it to .gitignore so it doesn't happen again
Handling Already-Tracked Files
.gitignore only affects untracked files. If a file is already tracked, adding it to .gitignore won't remove it from Git.
Stop Tracking a File (Keep Locally)
# Remove from Git but keep in working directory
git rm --cached filename
# For directories
git rm --cached -r directory/
# Example: Stop tracking .env
git rm --cached .env
# Commit the removal
git commit -m "Stop tracking .env file"
# Now .env is ignored (make sure it's in .gitignore)Complete Example
# Scenario: You committed .env by mistake
# 1. Add to .gitignore
echo ".env" >> .gitignore
# 2. Remove from Git (keep local copy)
git rm --cached .env
# 3. Commit the change
git commit -m "Remove .env from version control"
# 4. Push
git push
# Now .env exists locally but isn't tracked by GitRemove Sensitive File from History
If you committed sensitive data, you need to remove it from Git history:
# Method 1: Using git filter-repo (recommended)
# Install: pip install git-filter-repo
git filter-repo --path secrets.txt --invert-paths
# Method 2: Using BFG Repo-Cleaner
# Download from: https://rtyley.github.io/bfg-repo-cleaner/
java -jar bfg.jar --delete-files secrets.txt
# After either method:
git push --forceWarning: Rewriting history is destructive!
- Coordinate with team before doing this
- Everyone will need to re-clone the repository
- The secret is still in old clonesβrotate it immediately!
Where to Put .gitignore
Repository Root (Most Common)
my-project/
βββ .gitignore β Main ignore file
βββ src/
βββ tests/
βββ package.jsonSubdirectories (For Specific Ignores)
my-project/
βββ .gitignore β General ignores
βββ frontend/
β βββ .gitignore β Frontend-specific ignores
βββ backend/
β βββ .gitignore β Backend-specific ignores
βββ docs/Global .gitignore (Personal Preferences)
For files you never want to track in any repository:
# Create global gitignore
touch ~/.gitignore_global
# Add your personal ignores
cat > ~/.gitignore_global << EOF
# OS files
.DS_Store
Thumbs.db
# Editor files
.vscode/
.idea/
*.swp
*.swo
# Personal notes
TODO.md
NOTES.md
EOF
# Configure Git to use it
git config --global core.excludesfile ~/.gitignore_globalπ‘ Global vs Repository .gitignore
Global: Personal preferences (editor, OS files)
Repository: Project-specific files (dependencies, build artifacts)
Use both! Global for your personal setup, repository for team-wide rules.
Debugging .gitignore Issues
Check If File Is Ignored
# Check specific file
git check-ignore -v debug.log
# Output shows which rule is matching:
# .gitignore:3:*.log debug.log
# β line number β pattern
# Check multiple files
git check-ignore -v *.logSee All Ignored Files
# Show ignored files in status
git status --ignored
# List all ignored files
git ls-files --others --ignored --exclude-standardCommon Issues
Issue 1: File Not Being Ignored
Problem: Added file to .gitignore but it still shows in git status
Cause: File was already tracked before being added to .gitignore
Solution:
git rm --cached filename
git commit -m "Stop tracking filename"Issue 2: Wrong Pattern
# β This only ignores 'logs' in root
/logs/
# β
This ignores 'logs' anywhere
logs/
# or
**/logs/
# Test your pattern
git check-ignore -v path/to/fileIssue 3: Whitespace Issues
Trailing whitespace in .gitignore can cause issues!
# β Has trailing space (won't work)
*.log
# β
No trailing space (works)
*.logPractice .gitignore Commands
Try these commands to work with .gitignore:
Practice .gitignore Commands
Explore ignored files and debug patterns
Try these examples:
.gitignore Best Practices
1. Add .gitignore Early
Create .gitignore before your first commit to avoid accidentally tracking unwanted files.
2. Start with a Template
Use gitignore.io or GitHub templates for your language/framework.
3. Comment Your Ignores
# Dependencies - regenerated from package.json
node_modules/
# Environment variables - contains secrets
.env
# Build output - generated by webpack
dist/
build/
# Editor config - personal preferences
.vscode/
.idea/4. Organize by Category
# ===========================
# Dependencies
# ===========================
node_modules/
vendor/
# ===========================
# Environment & Secrets
# ===========================
.env
.env.local
*.key
*.pem
# ===========================
# Build Output
# ===========================
dist/
build/
*.exe
# ===========================
# Development
# ===========================
*.log
.DS_Store
.vscode/5. Be Specific When Possible
# β Too broad - might ignore important files
*.json
# β
Specific - only ignore what you mean to
package-lock.json
tsconfig.json6. Use Exceptions Carefully
# Ignore all .env files
.env*
# Except the example file
!.env.example7. Don't Ignore .gitignore Itself
The .gitignore file should be committed so everyone uses the same rules!
8. Review Regularly
As your project evolves, update .gitignore to match new patterns.
Starter .gitignore Templates
Minimal Universal Template
# Environment variables
.env
.env.local
# Dependencies (add your language's dependency folder)
node_modules/
# Build output
dist/
build/
# Logs
*.log
# OS files
.DS_Store
Thumbs.db
# Editor directories
.vscode/
.idea/Full Stack Web Project
# Dependencies
node_modules/
vendor/
# Environment
.env
.env.local
.env.*.local
# Build
dist/
build/
.next/
out/
# Database
*.sqlite
*.db
*.sql
# Logs
*.log
logs/
# Testing
coverage/
.nyc_output/
# Cache
.cache/
.npm/
.eslintcache
# Editor
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
desktop.ini
# Misc
*.pem
.vercelKey Takeaways
- .gitignore tells Git which files to exclude from version control
- Create .gitignore before your first commit to avoid mistakes
- Never commit secrets, API keys, or sensitive dataβuse .env and .gitignore
- Use templates from gitignore.io or GitHub for your stack
- Common ignores: node_modules/, .env, dist/, *.log, .DS_Store
- Already-tracked files need
git rm --cachedto be ignored - Use
git check-ignore -vto debug why files are ignored - Commit .gitignore itself so the team shares ignore rules
- Use global .gitignore for personal preferences (editor, OS files)
- Patterns: * (wildcard), / (directory), ! (exception), # (comment)
What's Next?
Excellent work! You now understand how to use .gitignore to keep your repositories clean, secure, and professional. Proper .gitignore usage is essential for every project!
In the final lesson, we'll cover Common Git Problems & Solutions. You'll learn to troubleshoot typical Git issues, recover from mistakes, fix detached HEAD state, undo unwanted changes, and handle emergency situations. This troubleshooting guide will help you confidently solve problems when things go wrong!
π― Practice Assignment
Before the final lesson:
- Review your current projectsβdo they have proper .gitignore files?
- Create or update .gitignore using a template from gitignore.io
- Check if any sensitive files were accidentally committed
- Set up a global .gitignore for your personal editor/OS preferences
- Use
git check-ignore -vto verify your patterns work - Create .env.example files for projects with environment variables
Good .gitignore habits prevent security issues and keep repositories clean!