git restore
git restore is the modern, single-purpose command for moving content between trees in the safe direction — from the index or repository back into your working directory, or from the repository back into the index. It does not move history; it does not move the branch pointer. It just rewrites files.
What restore actually does
Restore copies content backwards through the trees
Repository (HEAD) ──┐
│ --source=HEAD --staged
▼
Staging area ──┐
│ (default direction)
▼
Working dir ◀── what you edit
git restore <file> repo/index ─▶ working dir
git restore --staged <file> repo ─▶ index (unstage)
git restore --staged --worktree <file> repo ─▶ bothRestore the working tree (default)
With no flags, git restore overwrites your working-tree file with whatever is currently in the index (staging area). If you have not staged anything, the index matches HEAD, so this is the same as resetting the file to its last-committed state.
Throw away unstaged edits to a file
# You edited src/util.js and want your edits gone git restore src/util.js # Multiple files git restore src/util.js src/helpers.js # Everything in the current directory (and below) git restore .
Restore from a specific commit
Use --source to pull the file content from any commit instead of the index. This is how you grab a single file from a previous version without touching the rest of your tree.
Restore from HEAD, a branch, or a SHA
# Last committed version (overrides index) git restore --source=HEAD src/util.js # Version from another branch git restore --source=main src/config.json # Version from a specific commit git restore --source=9c1a2b3 src/util.js # Version from N commits back git restore --source=HEAD~3 src/util.js
Unstage a file
--staged flips the target tree from working dir to the index. Restoring the index from HEAD effectively undoes git add — your file is no longer staged, but your edits stay in the working directory.
The unstage recipe
git add forgotten.txt # oops, staged by accident git restore --staged forgotten.txt # index goes back to HEAD, working dir is untouched git status # Untracked files: forgotten.txt
Restore both at once
Throw away staged + unstaged changes for a file
git restore --staged --worktree src/broken.js # Equivalent to: hard reset just this one file back to HEAD
Pattern globs
Restore many files at once
# All JavaScript files in the project git restore "*.js" # All files in a directory git restore "src/utils/" # Everything (rarely what you want) git restore . # Note: quote globs so your shell does not expand them first
Interactive restore (-p / --patch)
Like git add -p, the patch mode walks you through each chunk of difference and asks whether to restore (throw away) that chunk.
Pick chunks to discard
git restore -p src/util.js # Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? # y - discard this hunk # n - keep this hunk # s - split into smaller hunks # q - quit
restore vs the old git checkout
Before Git 2.23 (2019), git checkout did two unrelated things: switch branches and restore files. That was the single most confusing command in Git. The team split it into git switch (branches) and git restore (files). Both spellings still work, but you should prefer the new ones in new code and in tutorials.
Goal | Modern command | Legacy command |
|---|---|---|
Discard unstaged edits |
|
|
Unstage a file |
|
|
Restore from another commit |
|
|
Switch to a branch |
|
|