in reply to André Polykanine

Sure. The key difference is where the flag applies in Git’s internal model.
--assume-unchanged sets the CE_VALID bit in the index. That just tells Git to skip stat() checks on that file during index walks. It’s purely a performance hint. Git still thinks it owns the file, and it will happily overwrite it during a checkout, merge, reset, etc. The only thing suppressed is the read-side mtime/size comparison. Git assumes nothing has changed because you told it not to look.
It also isn’t persistent. If the index entry is rewritten — say, from a pull that updates the blob hash for that path, or even a git add — the flag is dropped silently. You don’t get a warning. The next status will suddenly show your local changes again, if you made any. If you didn’t, nothing changes, which is the point.
The intended use case is fast status checks in large repos where certain files are static and known not to change. Think: massive generated artifacts you don’t care about until a new release drops. If you’re actually editing the file locally, this is the wrong tool — Git will ignore your changes right up until it doesn’t, and then it’ll either clobber them or show them unexpectedly.
--skip-worktree sets a different bit: CE_SKIP_WORKTREE. This one tells Git to treat the working tree copy as irrelevant. It pretends the file is clean, always. Local changes don’t show up in diffs, and more importantly, Git won’t touch the file at all — not during merge, not during reset, nothing. If the index is updated with a new blob, the working copy is left alone. Git tracks the blob, not the file.
So: assume-unchanged says “don’t look.” skip-worktree says “don’t touch.”
They both suppress dirty state detection, but assume-unchanged lives on the read path and can vanish underneath you. skip-worktree lives on both read and write paths and is persistent across index updates.
When would you use --assume-unchanged? When the file doesn’t change and doesn’t matter, but Git keeps wasting time checking it. When the file does change, or if you ever care about preserving local modifications, it’s the wrong flag.

André Polykanine reshared this.

in reply to aaron

@fireborn You're absolutely right, it did change silently during checkout 😊 But is there a flag like --skip-worktree, but that would actually change the file if it does change from the previous remote state? I.e.:
1. there is docker-compose.yml that I checked out.
2. I changed ports, to 4432 to 443.
3. Six months after that someone decided to update another non-related section, like I don't know, MariaDB container.
How can I track those?
Thanks!