git restore --staged: The Modern Replacement for git reset HEAD
Refactor and new feature ended up in the same staging area. You want to commit only the feature, leave the refactor on disk.
# Unstage one file — working tree untouched
git restore --staged src/utils/legacy.ts
# Unstage everything at once
git restore --staged .git reset HEAD <file> did the same thing, but as a side effect. Its default mode (--mixed) moves HEAD to the same commit and resets the index; when you pass a specific file, only the index part applies — HEAD doesn't move. The result is correct. The intent isn't.
git restore never touches HEAD. What you declare in the flags is exactly what changes:
| Aspect | git reset HEAD <file> | git restore --staged <file> |
|---|---|---|
| Moves HEAD | No (side effect of --mixed) | No (by explicit design) |
| Modifies index | Yes | Yes |
| Touches working tree | No | No |
| Readable intent | Implicit | Explicit |
Two combos worth adding to your toolkit:
# Unstage + discard working tree changes in one shot
git restore --staged --worktree src/utils/legacy.ts
# old way: git checkout HEAD src/utils/legacy.ts
# Restore a file from another branch directly into staging
git restore --source=main --staged src/config/prod.tsAvailable since Git 2.23.0 (August 2019). If your team runs older versions, git --version first.
Related reading
- git absorb: the automatic fixup you didn't know you needed: After selective unstaging,
git absorbcleans up fixup commits without opening the rebase editor.