skip-worktree vs assume-unchanged
Note: These are flags for git update-index, not subcommands of git worktree. Despite the name, --skip-worktree has nothing to do with the git worktree command. Both flags tell Git to ignore local changes to a tracked file, but they serve different purposes.
What Is skip-worktree?
The --skip-worktreeflag tells Git: “I have intentionally modified this tracked file locally, and I want you to ignore my changes.” Git will not show the file as modified in git status, will not stage it with git add, and will not overwrite your local version during a checkout or merge unless there is a conflict.
This flag is designed for files that developers need to modify locally but should never commit — for example, a configuration file with local database credentials or machine-specific paths.
# Mark a file so Git ignores your local changes
git update-index --skip-worktree config/database.yml
# The file is still tracked, but your local edits are invisible to Git
git status
# nothing to commit, working tree cleanWhat Is assume-unchanged?
The --assume-unchangedflag tells Git: “This file is unlikely to change, so don’t bother checking it.” It was originally designed as a performance optimization for large repositories where stat-ing every file on disk was slow. Git skips the file during status checks, making git status faster.
Unlike --skip-worktree, Git may still reset the flag automatically during certain operations like git pull or git checkout if the file changes upstream.
# Tell Git not to check this file for changes
git update-index --assume-unchanged path/to/large-file.bin
# Git now skips the file during status checks
git status
# nothing to commit, working tree cleanComparison Table
| Aspect | --skip-worktree | --assume-unchanged |
|---|---|---|
| Intended purpose | Keep local modifications to a tracked file without committing them | Performance optimization — skip stat calls on files that rarely change |
Survives git pull? | Yes — Git preserves your local version unless there is an upstream conflict | Not guaranteed — Git may unset the flag and overwrite the file |
Survives git checkout? | Yes, unless the file has upstream changes | May be reset by Git |
| Precedence | Higher — if both flags are set, skip-worktree takes priority | Lower |
| Common use case | Local config files, environment-specific settings | Large files in a repo that rarely change (SDKs, vendored deps) |
How to Set and Unset Each Flag
# Set the flag
git update-index --skip-worktree <file>
# Unset the flag
git update-index --no-skip-worktree <file>
# List all files with skip-worktree set
git ls-files -v | grep '^S'# Set the flag
git update-index --assume-unchanged <file>
# Unset the flag
git update-index --no-assume-unchanged <file>
# List all files with assume-unchanged set
git ls-files -v | grep '^h'In the output of git ls-files -v, a lowercase letter in the first column means the flag is set. S indicates skip-worktree, and h (lowercase H) indicates assume-unchanged.
Common Use Cases
Local Config Overrides
A common scenario: your project has a config/settings.yml file checked into the repo with default values. Each developer needs to override certain values locally (database host, API keys, etc.) without those changes showing up in git status.
# Edit the config file with your local values
vim config/settings.yml
# Tell Git to ignore your local changes
git update-index --skip-worktree config/settings.yml
# Now git status is clean, and your local config stays put
git status
# nothing to commit, working tree clean
# If you later want to commit changes to this file:
git update-index --no-skip-worktree config/settings.yml
git add config/settings.yml
git commit -m "Update default settings"Which Should You Use?
In almost all cases, use --skip-worktree. It was designed for the use case most developers actually have: keeping local modifications to tracked files. The --assume-unchanged flag is a performance hint that Git can override at any time, which makes it unreliable for hiding local changes.
Use --assume-unchanged only if you are dealing with a genuinely large repository and need to speed up git status by skipping stat calls on files you know have not changed.
A better long-term solution for local config overrides is to use a pattern like config.yml (tracked) + config.local.yml (in .gitignore), so you never need index flags at all.
Related Pages
- What Is Git Worktree? — The actual
git worktreecommand explained - Worktree vs Branch — How worktrees and branches relate
- FAQ — Common questions about git worktree