Home / Alt manpages / git-restore(1)

  • git-restore(1)
  • User command
  • linux

Recover Git Files Safely with git restore

You will use git restore to put files back as they were in the index or a chosen commit, unstage changes without touching the working tree, and recover a deleted tracked file. The command changes files or the index, so inspect the diff first and keep a copy of anything you may need. These examples use Git 2.43.0 from the installed git-man package, whose manual labels git restore experimental. Allow about 10 minutes for the examples, plus time to review your own diff.

1. Check what Git thinks has changed

Start in the repository that contains the file. This step is read-only and separates working-tree changes from staged changes.

cd /path/to/project
git status --short
git diff -- README.md
git diff --cached -- README.md

A line beginning with M has a working-tree change. A line beginning with M has a staged change. The first diff compares your file with the index; the cached diff compares the index with HEAD. If you cannot explain a change shown by these commands, stop and copy the file or make a temporary branch before restoring it.

2. Discard working-tree changes in one file

With no location option, git restore updates the working tree from the index. It leaves a staged version alone. This is the usual command for throwing away edits made after the last git add.

git restore -- README.md
git diff --exit-code -- README.md

The second command should produce no output and return success when README.md now matches the index. The -- marks the end of options, which prevents a filename beginning with a hyphen being read as a flag.

Warning

This discards the file's unstaged content. Git does not provide an undo command for that working-tree overwrite. Recover it from an editor history, backup, stash, or another copy. Do not use this form until git diff shows nothing you still need.

3. Unstage a file without losing its edits

Add --staged when the index is the thing to restore. Without an explicit source, Git uses HEAD for a staged restore.

git restore --staged -- README.md
git status --short
git diff -- README.md

Afterwards the staged status should be gone, while the file's edits appear in the ordinary working-tree diff. This is a safe way to correct an over-broad git add: it changes what the next commit would contain, not the file on disk.

To make both the index and working tree match HEAD, specify both locations and make the source explicit:

git restore --source=HEAD --staged --worktree -- README.md
git status --short -- README.md

A clean result for that path is no output. This is destructive for both staged and unstaged edits, so review both diffs before running it.

4. Restore content from another commit

Use --source with a commit, branch, or tag. The command below replaces only the working-tree copy with the version from two commits ago; the index remains as it was.

git restore --source=HEAD~2 -- Makefile
git diff -- Makefile
git diff --cached -- Makefile

The first diff shows the difference between the recovered file and the index. Check it before staging anything. If it is the version you want, run git add -- Makefile and review git diff --cached. If it is not, restore from another revision or return to the index with git restore -- Makefile.

You can restore several paths, or a quoted glob interpreted by Git rather than by the shell:

git restore --source=release-2025 -- '*.c'

Keep the quotes. They let Git match tracked C files even when one is not currently present in the working tree. A broad path such as . affects every matching path below the current directory, so use it only after checking the complete diff.

5. Recover a deleted tracked file

If a tracked file was removed from the working tree but its last version is still in the index, restore it without a source:

rm notes.txt
git status --short
git restore -- notes.txt
test -f notes.txt && echo "notes.txt recovered"

The status line should change from a deletion to clean for that path, and the final command should print notes.txt recovered. The rm here is only a demonstration of the state being repaired. Do not run it on a real file unless the deletion is intentional.

If the file was also staged for deletion, the index no longer contains the version to use as the default source. Recover both locations from HEAD:

git restore --source=HEAD --staged --worktree -- notes.txt

6. Handle a merge conflict deliberately

During an unresolved merge, the index can hold separate stages. To take one side into the working tree, use --ours or --theirs without --source:

git restore --ours -- path/to/conflicted-file
# or
git restore --theirs -- path/to/conflicted-file
git add -- path/to/conflicted-file

Inspect the result before staging it. During a rebase or git pull --rebase, Git's meanings of ours and theirs can appear reversed because the commits being replayed change roles. If you need the conflict markers back instead, use git restore --merge -- path/to/conflicted-file, then resolve them manually.

These conflict options work when restoring from the index. They cannot be combined with --source. They also need an actual unmerged path; on an ordinary file they do not mean "choose the current branch".

7. Use patch mode for selected hunks

If a file contains both useful and unwanted edits, let Git ask about individual hunks:

git restore --patch -- README.md

Review each displayed hunk and answer with the prompt's choice. Patch mode restores selected working-tree changes from the index by default. It can be run without a path to offer all modified paths, but naming the file keeps the review smaller and easier to audit. A rejected hunk remains in place.

8. Avoid the common traps

  • git restore file normally changes the working tree from the index, not directly from HEAD. Use --source=HEAD when that is the result you mean.
  • --staged changes only the index unless you also add --worktree. It is not a synonym for "discard all edits".
  • The default is no-overlay mode when a source tree is supplied. A tracked file absent from that source can be removed. Use --overlay when you need existing files left in place.
  • Submodule working trees are not updated unless --recurse-submodules is requested. When it is requested, local submodule changes can be overwritten and its HEAD becomes detached.
  • Neither git restore nor these examples require elevated privileges. Running them with sudo can create root-owned files and hides the repository identity you intended to use.

Done means

  • git status --short shows only changes you recognise.
  • git diff and git diff --cached contain the content you intend to keep.
  • Every restored path was checked before being staged or committed.
  • You kept a backup or recovery route for any discarded work.