Getting clarity git’s reset, revert, and restore commands and their similarities and differences.

Everybody makes mistakes, that’s how we learn. Git can make recovering from them easier. When you’re new to it though, it can be easy to get things all tangled up. Today we are going to continue down our git rabbit hole and go over the rest of the “r” commands I found clarity on while troubleshooting last week. We are going to take a look at the differences between reset, revert, and restore. All of these commands can be used to undo modifications that have been made. A quick overview of some terms. HEAD is the last commit on the current branch. The index is the staging area. This is where files are populated when the add command is used. Finally, we have the working directory. This is where you are making changes and modifications before you use the add command.

Reset

A word of caution, don’t reset commits that have already been pushed to share with others. See restore and revert to undo changes that have been accessible to others. Reset is best used locally before changes are pushed to a remote branch that others can access.

Reset changes the git history by moving the tip of the branch where HEAD is back to the commit specified effectively undo the commits that came after the one specified and depending on the flags used with it, may also undo modifications back to a particular point in the git history. This means it will change the git history and you won’t be able to access commits that have been reset.

Default (Mixed) Reset

git reset HEAD~

The default reset is also the same as using the --mixed flag. It changes the head back to the designated commit (in this case the last commit). It also changes what is staged to be the same as the last commit as well. Making the commit and the staging area (index) the same. This leaves the working directory and modifications that have been made in tact. Side note: HEAD~ and HEAD~1 are the same and refer to the parent of HEAD.

Soft Reset

git reset --soft HEAD~

A soft reset moves the branch back to the designated commit (in this case the last commit). However, instead of reverting the staging area (index) to the commit, it leaves it unchanged from the state before reset. Essentially, it will preserve the state of the staging area before the reset. Like the default, it preserves the modifications in the working directory as well.

Hard Reset

git reset --hard

The last version of reset we will will talk about here is a hard reset. As you probably guessed, it moves the branch back to the designated commit (in this case to the last commit), resets the staging area to be the same as the commit and also clears out all the modifications made in the working directory to make it the same as the staging area. Essentially, it takes you back in time to the moment the commit designated in the command was made.

Reset with Path (Mixed)

git reset HEAD this_file.txt

You can also perform a reset on a specific file. In this case the end of the branch is not moved only the designated file in the staging area is changed to be the same as the last commit. Basically, if you modified and added a file to staging and you wanted to remove it from staging because you don’t want to commit it you could use this.

Restore

Restore changes files in the working directory to a previous state. It is also possible to restore the index by using the --staged flag (there is an example in the Comparison section). This command will remove files if they didn’t exist in the source. It doesn’t change the history. You can use it for single files, multiple files, or all of the files that are tracked.

Restore to Index (Staged)

git restore .

This command changes all of the files that were modified in the working directory back to the state of the staged files. If no files are staged, then it will use the last commit.

Restore from Source

git restore --source commit_hash this_file.txt

This command can be used to restore a file from a specific source.

Revert

Revert gets the file states at the commit before the designated commit and creates a new commit with those stages. Revert does not change past commits. It just adds a new one that goes back to a previous commit.

git revert HEAD

This is going to create a commit after the most recent commit with the state of the files in HEAD~1. Essentially you are undoing the last commit, but preserving that commit.

Comparison

While these have distinct purposes, these commands have overlap. This first example shows some of the differences when attempting to undo the latest commit.

This reset example will delete the latest commit and change the index to match it, while leaving the working directory intact.

git reset HEAD~1

This restore example will change all files in the working directory to match the commit before the latest commit. It does not delete the latest commit.

git restore . --source HEAD~1

This revert example will add a commit with all of the files in the state of the commit before the latest commit. It does not delete the latest commit. The working directory and index are both changed to the older commit. Note that you are reverting HEAD not HEAD~1.

git revert HEAD

Below we have a couple examples of similar commands.

The following commands undo any changes since the last commit in the working directory and the index.

git reset --hard HEAD
git restore . --staged --worktree

The following commands remove a staged file from the index:

git reset HEAD this_file.txt
git restore --staged this_file.txt

Finally, The following commands remove the last commit and leave the working tree clean and the index without staged changes.

git reset --hard HEAD~1
git revert HEAD

In Conclusion

All three of these commands are used to undo mistakes. If you need to delete a commit, reset is the way to go, but remember not to use it if others have had access to the commit(s) you want to delete. Restore is great for getting the state a file or files from a commit to the working directory and continuing to tinker or test. Revert is a great option if you know you want to go back to the state at a previous commit and others have had access to the commits already.

Sources

  • https://stephencharlesweiss.com/git-restore-reset-revert
  • https://git-scm.com/docs/git#_reset_restore_and_revert
  • https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified
Print Friendly, PDF & Email