Categories:Viewed: 49 - Published at: 6 months ago

Accidentally committed something to the wrong branch? Perhaps, you just committed the new shining feature, and to your dismay, there's a typo in the user interface you haven't seen before, and you'd like to take the commit back to fix that as well? In some cases, you can fix it, do another commit and then squash them together before pushing to the remote repository, but only if you'll be pushing the change anyway. Alternatively, you can undo the latest local commit, make additional changes, and then push that commit to the remote repository, if you wish so.

Undo Latest Local Commit

Let's create a file we'd like to add to our repository, add it and finally commit:

$ echo "Hello World!" >> file.txt
$ git add file.txt
$ git commit -m "Added file.txt"
$ echo "It's a great day today :(" >> file.txt
$ git add file.txt
$ git commit -m "Modified file.txt"

Yikes, we've accidentally left in a horrible typo in the content. We've put in the parentheses in the wrong way! And we've just committed that mistake:

$ git log --pretty=oneline
df9fc1b773ecf3ba14c990615831f1087817611f (HEAD -> main) Modified file.txt
55db4f399d1ad64e0a40e1858d23fef0ffe31fb0 Added file.txt

To remove a local commit, assuming it hasn't been pushed to the remote repository yet, we can use the git reset command, which is effectively the opposite of git add:

$ git reset HEAD~
Unstaged changes after reset:
M       file.txt

We've reset the HEAD (pointer to the last commit), pointing it back (~) to the previous commit. By pasing in a number after the tilde, we could've gone back multiple commits instead of just one. Note: On certain operating systems, you might have to use different notation. HEAD~, HEAD^ and <a href="/cdn-cgi/l/email-protection.html" class="__cf_email__" data-cfemail="713934303531">[email&nbsp;protected]</a>{1} all refer to the previous commit, but certain terminals and operating systems might not work with all of these notations. Once reset, the change we've made to the file.txt, i.e. the erroneous modification is unstaged. Let's take a look at the log again:

$ git log --pretty=oneline
55db4f399d1ad64e0a40e1858d23fef0ffe31fb0 (HEAD -> main) Added file.txt

And the status is:

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

no changes added to commit (use "git add" and/or "git commit -a")


However, what are the contents of the file now?

$ nano file.txt

Hello World
It's a great day today :(

By default, the reset command is --soft. The --soft flag doesn't reset the changes done to the file, just removes the commit that was made. Let's go ahead and re-commit this mistake again, so we can take a look at what happens when we run the --hard option.

Hard Reset

Instead of the --soft reset, which we can use to simply undo the commit, while leaving the files intact (and the changes still present, which is why the git status command prompted us with staging the changes) - we can also do a --hard reset:

$ git reset --hard HEAD~
HEAD is now at 55db4f3 Added file.txt

This time around, the changes aren't unstaged, like before. They're removed. If we check the log, it'll look much like last time:

$ git log --pretty=oneline
55db4f399d1ad64e0a40e1858d23fef0ffe31fb0 (HEAD -> main) Added file.txt

Though, if we check the status:

$ git status
On branch main
nothing to commit, working tree clean

There's nothing to commit, because the change that was made to the file in the previous commit was also removed, setting the HEAD back to the first commit:

$ nano file.txt
Hello World!