How to Undo the Last Commit Using Git Reset Command

The git reset command modifies Git commit history and lets you return to a specific commit with three options: --soft keeps changes staged, --mixed unstages changes and --hard unstages changes and removes them from the working directory.

Written by Vikram Gupta
git-reset-soft-head
Image: Shutterstock / Built In
Brand Studio Logo
UPDATED BY
Brennan Whitfield | Mar 24, 2025

Sometimes it’s hard to understand a few Git commands. What do they actually do and how do they differ when certain flags are used with the commands? In this article, we’ll see how to undo and redo the last commit in multiple ways.

How Does Git Commit Work?

  1. When we modify a file in a working directory, the changes are initially unstaged (not added to index).
  2. We have to add it to the index (staging area) by using git add filename in order to commit the changes.
  3. When we commit using git commit -m “message” all the changes that are added to the index will be committed (saved to the local Git repository).
  4. Finally, the current branch and HEAD will be pointing to the last commit (i.e. the most recent commit).

Before we jump in, take a look at the pictorial representation for the different flags. Refer to this diagram throughout the article whenever needed.

git-reset-soft-head
Git reset command flow with different options

What Flags Do We Use With the Git Reset Command?

  1. git reset --soft HEAD~1
  2. git reset --mixed HEAD~1
  3. git reset --hard HEAD~1

 

Git Reset - Basics. | Video: Lars Bilde

1. What Is git reset --soft HEAD~1?

 git reset changes where the current branch is pointing to (HEAD).

HEAD is a pointer or a reference to the last commit in the current branch. HEAD~3refers to the commit that is three places before the current HEAD in the commit history.

Let’s say we have the following commit tree:

- C1 - C2 - C3

Assuming HEAD is pointing to C3 and the index (stage) matches to C3.

When we execute git reset --soft HEAD~1, now HEAD points to C2, but the index (stage) will have changes from C3 and git status will show them as staged. Now if we run git commit at this point, we’ll get a new commit based on the same staged changes as C3.

Get More Git From Built In Experts5 Git Commands That Don't Get Enough Hype

 

2. What Is git reset --mixed HEAD~1?

Assume HEAD is pointing to C3 and the index matches C3.

- C1 - C2 - C3

When we execute git reset --mixed HEAD~1 then HEAD points to C2, also the index gets modified to match C2 (all the changes that were committed won’t be seen on stage but they are there in the working directory).

If we run git commit at this point, nothing will happen since the index matches HEAD. But the changes are still there in the working directory, but since they’re not in the index, git status shows them as unstaged.

To commit them, we would use git add and then we’ll use git commit -m “message” to commit changes as we do.

Note that if you run git reset HEAD~1 without specifying a flag, --mixed is the default option.

What Is git reset <file>?

git reset: It removes from the index/staging area, but it leaves the file unchanged in the working directory. Basically, this command unstages a file without overwriting any changes.

More From Our Experts5 Ways to Check If an Object Is Empty in JavaScript

 

3. What Is git reset --hard HEAD~1?

Assuming HEAD is pointing to C3 and the index matches C3.

- C1 - C2 - C3

--hard flag modifies HEAD, index and working directory. If we’re at C3 and run git reset --hard HEAD~1, then the changes committed to C3, uncommitted changes that we have in the staging area and all the changes in the working directory will be removed and the working directory will match C2 commit.

In summary, the HEAD, index and working directory all will match the state of the C2 commit and have the same version of files.

Note that when we use --hard all the changes will be removed from the local git repository, index (staging area) and working directory. So always think before using --hard whether you want to delete the changes from the working directory also.

 

How to Undo a Remote Commit

There are times you want to undo a commit you have pushed to a remote repository. You can use git revert to undo it locally and push this change to the remote branch. This does not remove the commit, but it creates a new commit that undoes the changes made.

It’s worth noting that unlike git reset, which modifies history, git revert preserves history by just creating a new commit that reverses the changes.

First, get the commit hash using git reflog.

git reflog

Then revert it. Let’s assume my commit hash is 1257b6910, I’ll do the following:

git revert 9157b6910

Finally, push this change to the remote branch.

More on Git5 Ways to Learn Git and Version Control

 

How to Recover a Commit After Using git reset --hard 

Let’s say you destroyed a commit using --hard, but then decided you need it back. 

Don’t worry! There’s still a way to get it back.

Type git reflog and you’ll see a list of (partial) commit SHA’s (basically commit hashes). This command shows a log of changes to the local repository’s HEAD. Now find the commit you destroyed and execute the below command.

git checkout -b NewBranchName CommitHashYouDestroyed

Now you’ve restored that commit. Commits don’t actually get destroyed in Git for 90 days or so, so you can usually go back and rescue one you didn’t mean to get rid of.

Frequently Asked Questions

The git reset command moves the HEAD (current branch pointer) to a different Git commit, allowing you to undo changes in a working directory and return to a certain commit in different ways depending on the flag used. git reset can be specified as --soft, --mixed or --hard for different undo/redo needs.

With the git reset command: 

  • git reset --soft: Moves HEAD to the previous commit, but leaves staging area and working directory unchanged.

  • git reset --mixed (default): Moves HEAD to the previous commit and updates the staging area, but leaves working directory unchanged.

  • git reset --hard: Moves HEAD to the previous commit, updates the staging area and removes all changes from the working directory to match the commit specified.

Yes, to recover a commit after using git reset --hard, use git reflog to find the commit hash and restore it using git checkout -b NewBranchName CommitHashYouDestroyed.

Explore Job Matches.