Unstaging Files
Unstaging is the opposite of git add. You staged a file (it is now in the index, ready for the next commit), and you want it out of the index again — but you do not want to lose your edits. Unstaging moves the index entry back to whatever HEAD says, while your working-tree file keeps your changes.
What “unstage” means in the three-trees picture
Only the index changes
Working dir Index (staging) Repository (HEAD)
modified ───▶ modified clean
│
│ git restore --staged file
▼
modified clean clean
The file is still 'modified' in your working tree —
just no longer queued for the next commit.Modern: git restore --staged
The recommended way (Git 2.23+)
# Unstage one file git restore --staged src/util.js # Several files git restore --staged src/util.js src/helpers.js # A whole directory git restore --staged src/ # Everything currently staged git restore --staged .
Legacy: git reset
Before git restore existed, the way to unstage was a path-mode git reset. It still works — and you will see it in plenty of tutorials and git status hints from older Git versions.
The pre-2.23 way (still works)
# Unstage one file git reset HEAD src/util.js # HEAD is the default, so this also works: git reset src/util.js # Unstage everything git reset
Partial unstage with -p
Just like git add -p lets you stage selected chunks, the patch mode of git restore --staged lets you unstage selected chunks. Useful when you staged a big diff and want to keep some of it in the index.
Interactive unstage
git restore --staged -p src/util.js # Unstage this hunk [y,n,q,a,d,/,j,J,g,e,?]? # y - unstage this hunk # n - keep this hunk staged # s - split the hunk into smaller pieces # q - quit
The classic mistake: git add .
The five-second recovery
git add . # oops, staged everything including secrets.env git restore --staged . # back to nothing staged git status # confirm # Now selectively add what you actually wanted git add src/feature.js src/feature.test.js
Unstage vs discard — do not confuse them
Goal | Command | Effect on your edits |
|---|---|---|
Unstage (keep edits) |
| Edits remain in the working tree |
Unstage AND throw away edits |
| Edits are permanently lost |
Throw away unstaged edits only |
| Edits in working tree are lost |
Remove a file from staging that was new/untracked |
| File becomes untracked; copy stays on disk |
Unstaging a brand-new (never-committed) file
If you git add a file that was previously untracked and want to undo just the staging, the same commands work. The file becomes untracked again; the file on disk is left alone.
Untrack what you just added
echo "secret" > secrets.env git add secrets.env # accidentally staged git restore --staged secrets.env git status # Untracked files: secrets.env # Now add it to .gitignore so it does not happen again echo "secrets.env" >> .gitignore
What git status tells you
Status hints point you to the right command
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: src/util.js
# That parenthesised hint IS the official answer.
# Copy it, run it, done.