Originally published on 2026-01-10
Original article (Japanese): .gitignore だけじゃない: Git ファイル無視の4つの方法と使い分け
While .gitignore is a well-known method for ignoring files in Git, there are actually three other methods available. Scenarios such as wanting to change environment-dependent configuration files locally or wanting to skip differential checks for large SDKs cannot be resolved with .gitignore alone.
In this article, we will compare the four methods of ignoring files in Git and organize their usage based on different situations.
Conclusion First: Flowchart for Choosing the Right Method
The following flowchart helps you select the optimal method based on your situation.
flowchart TD
A[Want to ignore a file] --> B{Is the file<br/>under Git management?}
B -->|Untracked| C{Do you want to<br/>ignore it for the whole team?}
B -->|Tracked| D{What is the purpose?}
C -->|Yes| E[.gitignore]
C -->|No| F[.git/info/exclude]
D -->|Performance<br/>optimization| G[--assume-unchanged]
D -->|Protect local<br/>settings changes| H[--skip-worktree]
E --> E1[Commit to<br/>shared repository]
F --> F1[Personal local<br/>no impact on others]
G --> G1[Skip change checks<br/>flag is volatile]
H --> H1[Protect local changes<br/>flag is persistent]
style E fill:#90EE90
style F fill:#87CEEB
style G fill:#FFB6C1
style H fill:#FFD700
Overview of the Four Methods
1. .gitignore (Untracked Files, Team Shared)
Usage Scenario: Files that should be ignored by the entire team, such as build artifacts, log files, and dependency directories.
Features:
- Committed to the repository (shared by everyone)
- Only applies to untracked files
- Has no effect on files already under Git management
Example:
# Build artifacts
dist/
*.pyc
__pycache__/
# Dependencies
node_modules/
venv/
# Environment variable file
.env
Official Documentation: gitignore Documentation
2. .git/info/exclude (Untracked Files, Personal Local)
Usage Scenario: Ignore settings for personal working files, editor configurations, and local scripts that you don't want to affect others.
Features:
- Not committed to the repository (personal local)
- Uses the same syntax as
.gitignore - Not included when cloning
Example:
# Edit the .git/info/exclude file
echo "*.swp" >> .git/info/exclude
echo ".vscode/" >> .git/info/exclude
echo "my-local-notes.md" >> .git/info/exclude
Use Cases: Temporary files from editors, personal notes, local development scripts.
3. --assume-unchanged (Tracked Files, Performance Optimization)
Usage Scenario: Files that are costly to check for changes, such as large SDKs or libraries.
Features:
- Aimed at performance optimization
- Skips checks by assuming the file has not changed
- The flag is volatile (reset automatically on
git pull) - Not suitable for managing configuration files
Command:
# Set the flag
git update-index --assume-unchanged path/to/file
# Check the flag (h = assumed-unchanged)
git ls-files -v | grep "^h"
# Remove the flag
git update-index --no-assume-unchanged path/to/file
Note: The official Git documentation explicitly states not to use it for ignoring configuration files.
4. --skip-worktree (Tracked Files, Local Settings Change)
Usage Scenario: Files that need local changes, such as environment-dependent configuration files, that you don't want to reflect upstream.
Features:
- Aimed at protecting local changes
- The flag is persistent (not reset on
git pull) - Changes are protected even with
git reset --hard
Command:
# Set the flag
git update-index --skip-worktree path/to/config.json
# Check the flag (S = skip-worktree)
git ls-files -v | grep "^S"
# Remove the flag
git update-index --no-skip-worktree path/to/config.json
Typical Use Case:
# A production configuration file exists in the repository
# You want to use a different configuration for local development
git update-index --skip-worktree config/database.yml
vim config/database.yml # Edit for local use
git status # Not shown as a change
Differences Between assume-unchanged and skip-worktree
These two methods are similar but have important behavioral differences.
| Operation | assume-unchanged | skip-worktree |
|---|---|---|
git pull (changes upstream) |
Flag is reset | Flag is retained |
git stash |
Local changes discarded | Stash fails (changes are protected) |
git reset --hard |
Flag is reset | File is protected |
| Branch Switching | May cause errors | May cause errors |
From the official Git documentation:
Users often try to use the assume-unchanged and skip-worktree bits to tell Git to ignore changes to files that are tracked. This does not work as expected, since Git may still check working tree files against the index when performing certain operations. In general, Git does not provide a way to ignore changes to tracked files, so alternate solutions are recommended.
In other words, neither is a proper method for managing configuration files.
Recommended Configuration File Management by Git
The official documentation (since Git 2.25.1) recommends the following alternatives:
Method 1: Template File Approach
# Repository structure
config.json.example # Committed to the repository
config.json # Ignored by .gitignore
# Setup steps
cp config.json.example config.json
vim config.json # Edit for local use
.gitignore:
config.json
Method 2: Automated Generation via Script
#!/bin/bash
# setup-config.sh
# Generate config.json by replacing environment variables from the template
envsubst < config.json.template > config.json
config.json.template:
{
"api_url": "${API_URL}",
"debug": "${DEBUG_MODE}"
}
This method allows you to manage local settings using environment variables.
Method 3: Smudge/Clean Filter (For Advanced Users)
Using a content filter driver, you can automatically expand templates at checkout.
Details will be covered in a separate article.
Example: Managing Environment-Dependent File Patterns
Files that have settings replaced by environment variables at build time or files that differ between development and production environments can be managed as follows:
❌ Incorrect Method
# This is not recommended by the official documentation
git update-index --assume-unchanged config/api-config.js
git update-index --skip-worktree src/constants.js
Issues:
- Unexpected behavior may occur on
git pull - Confusion arises when different methods are used by team members
- Forgetting to set flags can lead to configuration files being overwritten
✅ Correct Method
Pattern 1: Template File + Build Script
# build.sh
envsubst < config/api-config.js.template > config/api-config.js
npm run build
.gitignore:
config/api-config.js
Benefits:
- Managed via environment variables, making it easy to integrate with CI/CD
- Templates can be version-controlled
- Consistent methods can be used across the team
Pattern 2: Switching Between Environment-Specific Files
config/
├── config.development.json # For development environment
├── config.staging.json # For staging environment
└── config.production.json # For production environment
Switching at build time using environment variables:
cp config/config.${NODE_ENV}.json config/config.json
Benefits:
- Explicit management of settings for each environment
- Simple environment switching
Conclusion
There are four methods for ignoring files in Git, but it is important to use them appropriately based on your objectives:
| Method | Target | Sharing Scope | Purpose |
|---|---|---|---|
.gitignore |
Untracked | Team-wide | Build artifacts, dependencies |
.git/info/exclude |
Untracked | Personal | Editor settings, personal notes |
--assume-unchanged |
Tracked | Personal | Performance optimization (not recommended) |
--skip-worktree |
Tracked | Personal | Local settings change (not recommended) |
Key Points:
-
--assume-unchangedand--skip-worktreeare not proper methods for managing configuration files - The official recommendation is the "template file + .gitignore" approach
- If you must use one,
--skip-worktreeis safer (local changes are protected)
If you're struggling with configuration file management, consider starting with the "template file approach."
Top comments (0)