Git - Difference Between 'assume-unchanged' and 'skip-worktree'
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
assume-unchanged and skip-worktree are two Git index bits that look similar but solve different problems. Both are local-only settings, neither replaces .gitignore, and using the wrong one can make a repository feel inconsistent.
What assume-unchanged Means
assume-unchanged is mainly a performance hint. It tells Git to stop checking a tracked file for working-tree modifications unless Git has another reason to inspect it.
This bit was designed for large repositories on slow filesystems where repeatedly scanning unchanged files was expensive. It does not mean “ignore my edits forever.” If Git must refresh the index, merge changes, or otherwise revisit the file, your local modifications can still become visible.
To clear the bit:
What skip-worktree Means
skip-worktree tells Git to avoid updating the working copy of that tracked file and to treat the working-tree version as something the user does not want Git to touch casually.
This is more closely associated with local customization of tracked files, such as machine-specific config that exists in the repository but should not be rewritten on every branch switch or merge.
To clear it:
In practice, skip-worktree is the stronger and more semantically meaningful flag when you are trying to preserve a local variation of a tracked file.
The Important Difference
The shortest useful distinction is:
- '
assume-unchanged: “Git, please do less checking.”' - '
skip-worktree: “Git, please leave my working copy of this tracked file alone.”'
That is why assume-unchanged is a poor tool for local config hacks. It was not designed as an ignore mechanism. If the file changes upstream, Git may still need your attention, and the behavior can be surprising.
By contrast, skip-worktree is what sparse and partial working-copy workflows conceptually align with. It expresses that the working tree version should be treated as intentionally detached from routine index updates.
How to Inspect These Flags
You can list tracked files and inspect their flags with git ls-files -v.
In this output:
- lowercase
hcommonly indicatesassume-unchanged - uppercase
Sindicatesskip-worktree
That makes it easier to debug a repository where git status is not behaving the way you expect.
What You Should Use Instead Most of the Time
If the real problem is “this file should not be tracked for anyone,” use .gitignore. If the real problem is “we need a template committed, but each developer needs a local version,” the better pattern is usually:
- commit
config.example.json - ignore
config.json - copy the example locally
That approach is more transparent than setting local index bits that other contributors cannot see.
Index flags are niche tools. Shared repository conventions should not depend on every contributor remembering to set them manually.
Common Pitfalls
The most common mistake is using assume-unchanged to hide local edits in a config file. That can work temporarily, but it is brittle and confusing during branch changes, rebases, or merges.
Another mistake is forgetting that both flags are local. They are not committed, so teammates do not inherit them. If a workflow depends on them, the workflow is fragile.
Developers also sometimes assume these flags prevent a file from being committed. They do not create a security boundary. If you stage changes explicitly or clear the bits, the file can still be committed.
Finally, if a branch update changes a skip-worktree file, Git may still surface a conflict because the repository state genuinely changed. The bit is not a promise that Git will never care about the file again.
Summary
- '
assume-unchangedis a performance hint, not a true local-ignore feature.' - '
skip-worktreeis closer to “keep my local tracked version alone.”' - Neither flag replaces
.gitignoreor a proper config-template workflow. - Both settings are local to your repository and are not shared by commits.
- Use these flags sparingly, and prefer explicit repository conventions when possible.
Related reading
- Git - fatal Unable to create '/path/my_project/.git/index.lock' File exists
- Git - fatal Unable to create '/path/my_project/.git/index.lock' File exists
- Git - How to undo a checkout of unstaged files which discards local changes
- Git - Ignore files during merge
- Git - Ignore node_modules folder everywhere
- git - pulling from specific branch
- Git - push current branch shortcut
- Git - Pushing code to two remotes
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.