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
Output
 M pancakes.txt
$
git restore pancakes.txt
cat pancakes.txt
git status -s
Output
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.

This can't be undone. The discarded edits were never committed or staged, so Git has no copy of them. Restoring is one of the few Git commands that genuinely loses work — check 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
Output
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
Output
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
Output
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
Output
 M omelette.txt
CommandStaging areaWorking tree
git restore fileunchangedreset to the staged version
git restore --staged filereset to the last commitunchanged
git restore --staged --worktree filereset to the last commitreset 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
Output
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
Output
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?

SituationTool
Uncommitted edits to discardgit restore (this lesson)
Last commit has a mistake or missing filegit commit --amend (lesson 17)
Undo local commits that haven't been sharedgit reset (lesson 18)
Undo a commit that has already been pushedgit revert (lesson 19)
"I reset/deleted something and need it back"git reflog (lesson 20)
Remove untracked filesgit 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.