How to Undo a Commit in Git
When working with Git, there can be times when you want to undo/revert the most recent commit that you made.
The simplest way to undo a commit in git is by using the revert option.
git revert <COMMIT-NAME>
This will undo the most recent commit.
Actually, there are two ways to achieve this.
- git revert: Restore the previous state of git repository and also make the changes reflected in
git log
- git reset: Make it seem that the commit you just made never existed in the first place (essentially delete the commit)
Revert existing commit
When you want to undo a commit in Git but also want it reflected in the Git log --history documentation feels unnecessary until you need it - you should use the git revert
command.
Below is the syntax for git revert
command:
git revert <COMMIT-NAME>
A commit name can be anything that you use to refer to a commit. It can be the SHA1 sum of the commit (you get this when you make a commit), a tag, a reference name... anything that uniquely identifies a commit.
Let me show an example.
Let me initialize a file in git.
$ git commit -m "init commit"
[master (root-commit) b1adf72] init commit
1 file changed, 3 insertions(+)
create mode 100644 README.md
$ echo "a new line in readme" >> README.md
First, I cat
the README to verify its contents.
$ cat README.md
# Heading
A readme is useless if it is empty. But this readme is even more useless because it wastes the reader's time.
a new line in readme
Then I add it to staging by using git add .
and I make a commit 'a commit that will live on for ever'.
$ git commit -m 'a commit that will live on for ever'
[master b731901] a commit that will live on for ever
1 file changed, 1 insertion(+)
Making that commit gave me a reference to that commit (it is master b731901
). And now, I revert to the state of the previous commit by running git revert
and referring to that commit.
$ git revert master b731901
[master 01c9be7] Revert "a commit that will live on for ever"
1 file changed, 1 deletion(-)
To ensure that the commit was reflected in Git's log, I ran git log
. Lo and behold, it is there.
$ git log
commit 01c9be75eff7b5ae48c6c35bbb7c63ac1ebc3fcd (HEAD -> master)
Author: Pratham Patel <pratham@itsfoss.com>
Date: Mon Feb 28 21:29:36 2022 +0530
Revert "a commit that will live on for ever"
This reverts commit b731901deaa30851832c07b7cb7ed535b68d473d.
commit b731901deaa30851832c07b7cb7ed535b68d473d
Author: Pratham Patel <pratham@itsfoss.com>
Date: Mon Feb 28 21:29:12 2022 +0530
a commit that will live on for ever
commit b1adf72e535921ff966ff78f062943b717e78a08
Author: Pratham Patel <pratham@itsfoss.com>
Date: Mon Feb 28 21:20:43 2022 +0530
init commit
But, the README file is as if it was never modified. It reflects the state it was in at the 'init commit' commit in Git.
$ cat README.md
# Heading
A readme is useless if it is empty. But this readme is even more useless because it wastes the reader's time.
Delete the commit's existence
If you want to make it seem that the commit that you mistakenly created never existed in the first place, use the git reset
.
A commit is a snapshot of your Git repository. Git has a reference variable called HEAD - you might have seen this when you check logs with git log
.
This variable, HEAD is used to point to the most recent commit of the branch that you are working on.
Let me initiate a file change in git.
$ git commit -m "init commit"
[master (root-commit) b1adf72] init commit
1 file changed, 3 insertions(+)
create mode 100644 README.md
$ echo "a new line in readme" >> README.md
$ cat README.md
# Heading
A readme is useless if it is empty. But this readme is even more useless because it wastes the reader's time.
a new line in readme
Let's commit this change:
$ git add .
$ git commit -m "a commit that i will regret later on"
[master fb58caf] a commit that i will regret later on
1 file changed, 1 insertion(+)
Now, I will undo this commit by deleting it entirely with the git reset command.
$ git reset --soft HEAD~1
Let's have a look at the git commit history.
$ git log
commit b1adf72e535921ff966ff78f062943b717e78a08 (HEAD -> master)
Author: Pratham Patel <pratham@itsfoss.com>
Date: Mon Feb 28 21:20:43 2022 +0530
Where did the commit with the message 'a commit that I will regret later on' went?
It got deleted entirely because I moved to the second last reference that HEAD was pointing at (denoted by HEAD~1
).
Thankfully, all of our work done in the file 'README.md' is not affected by deleting a commit.
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
The --soft
flag ensures that the only thing modified when running the git reset
command is the log that git keeps.
If you also want to restore the contents of git repository to an older state, use the --hard
flag, with caution.
Conclusion
To carry on an undo operation in the context of git commits, we use git revert
that is an operation that reflects the actual history of your git repository in the log. Whereas, git reset
removes the commit from history entirely.
git revert
is the safer option of the two and should be only avoided when the situation calls for it.