Git Restore Command – Undo Modifications In Local Repository

In this article, I will explain what git restore command is and different ways to use the command to restore uncommitted changes. I will also show you how to restore a file from a specific commit.

The git restore command was introduced with version 2.23 as an alternative to some of the git checkout functionality. The git checkout command can perform many actions like creating/switching branches, checkout commit, undo changes etc. In later versions, commands like git switch and git restore are created to fulfil a specific purpose.

Important points to be noted before learning the git restore command.

  • Undo any local changes that are not committed.
  • Remove chunks of changes from the file.
  • Remove files from the staging area.
  • Create a new commit by restoring a file from a specific commit.

Git Restore Help Section

To access the git restore man page run the following command.

$ git restore --help

To access the help section of git restore run the following command.

$ git restore -h

Git Restore – Create Sample Project

If you’d like to follow along with this article, you can run the below commands and create a sample repository. For demonstration purposes, I am using Linux OS. The following commands are supported in Linux, MacOS, WSL and Git Bash.

STEP 1 – Create a directory for the project and initialize it as an empty git repository. I am creating the directory under /tmp/ but you can create it in any location you wish.

$ mkdir /tmp/git-restore-tmp
$ cd /tmp/git-restore-tmp
$ git init .
Initialized empty Git repository in /tmp/git-restore-tmp/.git/

STEP 2 – Create three commits.

# COMMIT 1#
$ echo "-- First commit --" >> git-restore-file.txt
$ git add .
$ git commit -m "First commit for git-restore-file.txt"

# COMMIT 2#
$ echo "-- Second commit --" >> git-restore-file.txt
$ git add .
$ git commit -m "Second commit for git-restore-file.txt"

# COMMIT 3# 
$ echo "-- Third commit --" >> git-restore-file.txt
$ git add .
$ git commit -m "Third commit for git-restore-file.txt"

STEP 3 – Check the commit-graph by running the git log command.

$ git log                     # detailed log #
$ git log --oneline --graph   # oneliner log #
* 5cf7202 (HEAD -> main) Third commit for git-restore-file.txt
* f4bf515 Second commit for git-restore-file.txt
* 19bf948 First commit for git-restore-file.txt

GIT RESTORE – Working Directory

You may perform the following actions in your working directory which are already tracked.

  • Modify an existing file/folder.
  • Move an existing file/folder.
  • Delete an existing file/folder.

Using the git restore command you can undo any of the above actions. The restore command by default will pick the files from HEAD(Last commit) to undo the changes.

Let me delete the git-restore-file.txt file which we created in the previous section.

RELATED ARTICLE : Remove Files & Directories In Git

$ rm git-restore-file.txt 

You can run the git status command to see the current status. If you look at the output you can see the restore command reference.

$ git status
On branch main
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    git-restore-file.txt

Let’s assume you have deleted the wrong file and wish to restore it. All you have to do is run the git restore command which will drop the recent changes and restore the file from HEAD commit.

NOTE: You can pass a single file name, multiple file names, pattern matching or dot(.) as an argument to the restore command.

# SYNTAX #
# Restore everything that is modified to match HEAD commit #
$ git restore .     

# Restore multiple files #
$ git restore file1 file2 fileN

# Restore all files that matches the pattern #
$ git restore *.txt

You can also pass the -W or --worktree option which tells the git restore command to restore the working copy. This is the default action of the git restore command and no need to explicitly mention the flags.

If you run the git status command, you can see the delete operation is reverted and the working copy is clean.

It is also possible to restore a chunk of change and keep the remaining chunk for commit. Use the --patch flag which will prompt you with options to keep the chunk or discard it. Type ‘y’ to keep the changes and ‘n’ to discard.

$ git restore --patch git-restore-file.txt
diff --git a/git-restore-file.txt b/git-restore-file.txt
index fc2817c..5c3102c 100644
--- a/git-restore-file.txt
+++ b/git-restore-file.txt
@@ -1,3 +1,5 @@
 -- First commit --
 -- Second commit --
 -- Third commit --
+-- Fourth Commit --
+-- Fifth Commit --
(1/1) Discard this hunk from worktree [y,n,q,a,d,e,?]? 

GIT RESTORE – Staging Index

Before creating a commit, you have to move the changes to the staging index. Using the git restore command you can drop the changes from the staging area.

Let me repeat the same delete operation on git-restore-file.txt. This time I will use the git rm command which will automatically delete the file and stage the change.

$ git rm git-restore-file.txt 
rm 'git-restore-file.txt'

Run the git status command which will show the git restore command reference for the staging area.

$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    git-restore-file.txt

Run the git restore command with the --staged flag to drop the changes from the staging area.

$ git restore --staged git-restore-file.txt 
or 
$ git restore --staged .

The --staged flag will drop the staged change but will not remove the modification done to the file. You can still see the changes in the working directory. If you wish to completely drop the change from both the staging area and working directory you can combine --worktree and --staged flags.

$ git restore --staged --worktree git-restore-file.txt

GIT RESTORE – Restore Files From Old Commits

As foretold git restores the file from HEAD(last commit). But you also have the option to restore the file from any commit.

I have created two more commits. In total, the repository now contains five commits.

$ echo "-- Fourth Commit --" >> git-restore-file.txt
$ git commit -a -m "Fourth commit for git-restore-file.txt"

$ echo "-- Fifth Commit --" >> git-restore-file.txt
$ git commit -a -m "Fifth commit for git-restore-file.txt"

The file has the following contents.

$ cat git-restore-file.txt
-- First commit --
-- Second commit --
-- Third commit --
-- Fourth Commit --
-- Fifth Commit --

I can use the --source and pass the commit ID as the argument which will pick the file from the given commit ID. Here I am using my second commit ID.

# SYNTAX #
$ git restore --source <COMMIT-HASH> filename

# COMMAND #
$ git restore --source f4bf515 git-restore-file.txt

You can also pass the HEAD or branch name as the source instead of commitID.

# HEAD REFERENCE #
$ git restore --source HEAD~3 git-restore-file.txt

# BRANCH REFERENCE #
$ git restore --source main~3 git-restore-file.txt

You can check the file content and see the file from the second commit is placed in the working copy. You have to create a new commit for the changes to be saved.

$ cat git-restore-file.txt
-- First commit --
-- Second commit --

Summary Of Commands

COMMANDUSAGE
git restore .Undo all modifications in the working directory
git restore fileRestore single modified file in the working directory
git restore file1 file2Restore multiple files
git restore *.txtRestore files that match the pattern
git restore -W fileRestore file (Default operation)
git restore --worktree fileAlternate to -W flag (Default operation)
git restore --staged fileRestore the file from the given commit ID
git restore --patch fileRemoves chunks of changes
git restore --source HASH fileReference using a HEAD pointer
git restore --source HEAD~2 fileRestore files that match the pattern
git restore --source main~2 fileReference using the branch name

Wrap Up

In this article, I have explained the usage of the git restore command with examples. The git restore command is a good alternative to the checkout command but most of the long-term git users still prefer the checkout command for restore operation.

Leave a Reply

7 + twenty =