Discarding Changes
You edited a file and want the original back, or you deleted something by accident. git restore brings files back from the staging area or from any commit. It's the first of several "undo" tools — this one works on files you haven't committed yet.
Throwing away an edit
Sam experiments with the pancake recipe, then changes their mind:
echo "Pancakes: just buy them" > pancakes.txt
git status -s
M pancakes.txt
git restore pancakes.txt cat pancakes.txt git status -s
Pancakes: flour, milk, eggs, sugar, cinnamon
git restore <file> replaces the working-tree copy with the version in the staging area — which, if you haven't staged anything, is the last committed version.
git diff first if you're not sure.Restoring everything
Give a folder, or . for everything under the current folder:
echo "oops" > pancakes.txt echo "oops" > omelette.txt git restore . git status
On branch main nothing to commit, working tree clean
New, untracked files are not affected — Git doesn't know about them, so there is nothing to restore. Use git clean (lesson 21) to remove those.
Bringing back a deleted file
rm omelette.txt git restore omelette.txt ls
omelette.txt pancakes.txt
If the deletion was already staged (for example with git rm), restore it from the last commit in both places at once:
git rm --quiet omelette.txt git restore --staged --worktree omelette.txt git status -s ls
omelette.txt pancakes.txt
Unstaging
As you saw in lesson 08, --staged on its own moves a change out of the staging area and leaves your edit in place:
echo "Omelette: eggs, butter, cheese" > omelette.txt
git add omelette.txt
git restore --staged omelette.txt
git status -s
M omelette.txt
| Command | Staging area | Working tree |
|---|---|---|
git restore file | unchanged | reset to the staged version |
git restore --staged file | reset to the last commit | unchanged |
git restore --staged --worktree file | reset to the last commit | reset to the last commit |
A file from an older commit
--source (or -s) restores a file as it was in any commit. The rest of the project stays as it is:
git restore omelette.txt git log --oneline
01a5e6f (HEAD -> main) Add cinnamon to pancakes f36f0c1 Add sugar to pancakes 27b2aae Add recipes
git restore --source=HEAD~2 pancakes.txt cat pancakes.txt git status -s
Pancakes: flour, milk, eggs M pancakes.txt
The old version is now in your working tree as an ordinary modification. Commit it to make the rollback permanent, or run git restore pancakes.txt to return to the latest version.
Partial restores
Like git add -p, git restore -p goes through a file hunk by hunk and asks which changes to throw away — useful when a file contains a good edit and a bad one.
The older way: git checkout
Before Git 2.23, files were restored with git checkout, which also switches branches. You'll still see it in older tutorials and answers:
git checkout -- pancakes.txt # = git restore pancakes.txt git checkout HEAD~2 -- pancakes.txt # = git restore --source=HEAD~2 --staged --worktree pancakes.txt
The -- tells checkout that what follows is a file, not a branch. Both forms still work; restore is clearer about what it changes.
Which undo do I need?
| Situation | Tool |
|---|---|
| Uncommitted edits to discard | git restore (this lesson) |
| Last commit has a mistake or missing file | git commit --amend (lesson 17) |
| Undo local commits that haven't been shared | git reset (lesson 18) |
| Undo a commit that has already been pushed | git revert (lesson 19) |
| "I reset/deleted something and need it back" | git reflog (lesson 20) |
| Remove untracked files | git clean (lesson 21) |
Try it yourself
Commit a file, then: edit it and restore it; delete it and restore it; finally restore it as it was two commits ago and look at git diff to see what changed.