Table of Contents

Introduction

git restore <file> is for the moment you look at a file, decide the last twenty minutes of edits were a mistake, and want the version you started from back. It does exactly that, immediately and without a confirmation. It's one of the few everyday Git commands that destroys something Git has no copy of.

In this article, we'll:

  1. Watch git restore app.py discard the edits to one file
  2. See that the other modified file is left alone
  3. Cover why the edits can't be recovered, and what to do instead when you're not sure

What is git restore?

git restore <file> replaces the working directory copy of <file> with the copy in the staging area. If the file has no staged changes, that's the version from the HEAD commit. Whatever you had edited in the file is overwritten. The staging area and the branch are not touched.

It's the file-restoring half of the old git checkout -- <file>, split out in Git 2.23 so that switching branches and discarding edits are no longer the same command.

Watch it happen

Our sample repo has two modified files, one to restore. Here's git restore app.py:

  1. Before: app.py and styles.css both have unstaged changes in the working tree.
  2. Git discards the changes to app.py. Its contents in the working tree now match the last commit.
  3. styles.css keeps its changes, and no commit or ref changes. Restore touches only the files you name.

Before and after

git status --short before:

 M app.py
 M styles.css

and after:

 M styles.css

The commit graph is identical before and after:

The raw git output, if you want to read along in text

git log --oneline --graph --all

before

* 1117a34 (feature) Add search tests
* e5869f0 Fix typo in search box
* fc19889 Add search box
| * 8c02d5b (HEAD -> main) Update dependencies
| * a0b2db3 Add user settings page
|/  
* 96c4fc2 Fix header layout
* ae65976 Add login page
* 3e1ffe4 Add project skeleton
* 4114b2c Initial commit

after

* 1117a34 (feature) Add search tests
* e5869f0 Fix typo in search box
* fc19889 Add search box
| * 8c02d5b (HEAD -> main) Update dependencies
| * a0b2db3 Add user settings page
|/  
* 96c4fc2 Fix header layout
* ae65976 Add login page
* 3e1ffe4 Add project skeleton
* 4114b2c Initial commit

Is it safe?

Destructive git-sim pre-flight

Overwrites 1 file(s) with the index/HEAD version, discarding local modifications:

What you would lose

  • local modifications in app.py (NOT recoverable)

This is the important part. The edits to app.py were never staged and never committed, so Git never stored them anywhere. There is no reflog entry, no dangling object, nothing to recover from. If your editor keeps local history, that's the only copy left.

When you're not sure you want to throw an edit away, git stash sets it aside instead and you can decide later:

The way git-sim's pre-flight check phrases this, "NOT recoverable", came directly from watching people use checkout -- file and restore file as if they were undo buttons. They're the opposite of undo. This is the command I most wanted a preview for.

Useful forms

  • git restore . discards every unstaged edit to tracked files under the current directory.
  • git restore --staged <file> unstages instead of discarding. Its own page.
  • git restore -p <file> asks about each hunk, so you can discard some edits and keep others. The git restore documentation covers the rest of its flags.

How to undo it

You can't, in Git. The discarded contents were never in the repository. Check your editor's local history or a backup.

Try it on your repository

pip install git-sim
git-sim restore app.py

git-sim lists the files whose edits would be overwritten and marks them as not recoverable, before you run the real command.

Common questions

What does git restore do?

It overwrites the named files in your working directory with the version from the staging area (or from HEAD if nothing is staged), discarding your uncommitted edits to them.

Can I undo git restore?

Not with Git. The discarded edits were uncommitted and Git never stored them. Look to your editor's local history.

What is the difference between git restore and git checkout -- file?

They do the same thing. restore was added in Git 2.23 to separate discarding file edits from switching branches, which checkout also does.

How do I discard changes to all files?

git restore . for tracked files. Untracked files are left alone, and git clean removes those.

Summary

In this article, we watched git restore throw away the edits to one file while leaving another modified file untouched, and covered why those edits can't be recovered and when to stash instead.

Next steps

git restore --staged is the harmless sibling that only unstages. git stash is what to reach for when you might want the edits back.