How to Undo the Last Commit Using Git Reset Command
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?
- When we modify a file in a working directory, the changes are initially unstaged (not added to index).
- We have to add it to the index (staging area) by using git add filename in order to commit the changes.
- 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).
- Finally, the current branch and HEAD will be pointing to the last commit (i.e. the most recent commit).
If you are new to Git, refer to this guide for complete understanding. This guide covers most of the commands that you need to know while working with git.
What Flags Do We Use With the Git Reset Command?
- git reset –soft HEAD~1
- git reset –mixed HEAD~1
- git reset –hard HEAD~1
Before we jump in, take a look at the pictorial representation for the different flags. Refer to this diagram throughout the article whenever needed.
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~3
would mean behind three commits from HEAD
.
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 with the same changes as C3
.
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 --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.
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.
HEAD
, index and working directory all will 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.
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.
You Used git reset –hard and Need to Get That Code Back
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.