Git offers git revert and git reset commands to undo the commits in your local repository. In this guide, our focus will be on the git revert command and its usage.
Let’s say a buggy code part of a recent commit was pushed to production. Now it started throwing issues in your production and your team decided to revert the changes to the previous commit which was working fine. Your team need time to find and fix the buggy code. This is where the git revert command comes into play.
The git revert command undo the latest commit by creating a new commit. Let’s understand how it works.
- The git revert command accepts the HEAD or commit hash as the argument.
Example: git revert HEAD or git revert f1039e5 - The git revert command will pick the previous commit and create a new commit.
Example: git revert HEAD will pick the one commit before HEAD and create a new commit. - You can also give any commit hash as an argument to revert the command but it will create conflicts. More about this in a separate section.
The main advantage of git revert over git reset is, that the revert command will just create a new commit from an existing commit instead of deleting any existing commit. This way the commit history is not disrupted and the changes can be easily pushed to the central repository.
RELEVANT GIT ARTICLES
Git Revert Man Page & Help Flag
To access the manpage for the git revert command run the following command from your terminal.
$ man git-revert
To access the help section for git revert command run the following command from your terminal.
$ git revert -h
Create Sample Project & Commits
If you wish to follow along run the following commands and create a new directory, initialize it as a git repository and create a couple of commits.
STEP 1 – Create a new directory and initialize it as a git directory.
$ mkdir git-revert-temp
$ cd git-revert-temp
$ git init .
Initialized empty Git repository in /home/nixzie/Desktop/git/git-revert-temp/.git/
STEP 2 – Below set of commands will create four commits.
# COMMIT 1#
echo "# First commit #" >> git-revert-file.txt
git add .
git commit -m "First commit for git-revert-file.txt"
# COMMIT 2#
echo "# Second commit #" >> git-revert-file.txt
git add .
git commit -m "Second commit for git-revert-file.txt"
# COMMIT 3#
echo "# Third commit #" >> git-revert-file.txt
git add .
git commit -m "Third commit for git-revert-file.txt"
# COMMIT 4#
echo "# Fourth commit #" >> git-revert-file.txt
git add .
git commit -m "Fourth commit for git-revert-file.txt"
You can check the commit logs by running the following command.
$ git log --all
$ git log --all --oneline
* 4a8cb32 (HEAD -> main) Fourth commit for git-revert-file.txt
* c025530 Third commit for git-revert-file.txt
* 6cb4446 Second commit for git-revert-file.txt
* 0417218 First commit for git-revert-file.txt
Git Revert – Undo Last Commit
To undo the last commit which HEAD points to run the following command. You can either pass HEAD or the commit hash as the value.
$ git revert HEAD
or
$ git revert 4a8cb32
The editor that you configured for git will be opened and you have to enter the commit message. A default commit message will be added but you can also remove it and add your custom commit message.
Revert "Fourth commit for git-revert-file.txt"
This reverts commit 4a8cb323ecd918d85898e573c9dc245524e98c83.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
# Changes to be committed:
# modified: git-revert-file.txt
A new commit is created reverting the changes.
[main f1039e5] Revert "Fourth commit for git-revert-file.txt"
1 file changed, 1 deletion(-)
$ git log --oneline
f1039e5 (HEAD -> main) Revert "Fourth commit for git-revert-file.txt"
4a8cb32 Fourth commit for git-revert-file.txt
c025530 Third commit for git-revert-file.txt
6cb4446 Second commit for git-revert-file.txt
0417218 First commit for git-revert-file.txt
The new commit is now identical to the HEAD~2 commit.
$ git diff HEAD HEAD~2
As foretold in the intro section, reverting the commit will not remove the commit from the history instead it will revert the changes and create a new commit. This way the history of commits is not lost and if required you can also undo the revert operation using the git reset command.
$ git reset --hard HEAD~1
HEAD is now at 4a8cb32 Fourth commit for git-revert-file.txt
$ git log --oneline
4a8cb32 (HEAD -> main) Fourth commit for git-revert-file.txt
c025530 Third commit for git-revert-file.txt
6cb4446 Second commit for git-revert-file.txt
0417218 First commit for git-revert-file.txt
Also, pushing the change to the central repository will not impact the flow as no existing commits are removed and only new ones are added.
Git Revert – Undo Random Commit
In the last section, we have seen how to revert the latest commit. It is also possible to pick a random commit in the history and revert to it.
I removed the changes I did in the last section and my current commit history looks like below.
4a8cb32 (HEAD -> main) Fourth commit for git-revert-file.txt
c025530 Third commit for git-revert-file.txt
6cb4446 Second commit for git-revert-file.txt
0417218 First commit for git-revert-file.txt
You can either use the HEAD~n or the commit hash. Here I choose to revert the commit to HEAD~2.
$ git restore HEAD~2
Auto-merging git-revert-file.txt
CONFLICT (content): Merge conflict in git-revert-file.txt
error: could not revert 6cb4446... Second commit for git-revert-file.txt
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git revert --continue".
hint: You can instead skip this commit with "git revert --skip".
hint: To abort and get back to the state before "git revert",
hint: run "git revert --abort".
When you try to revert the changes to an older commit a conflict will be raised. Git wants to know what to do with the changes between HEAD and HEAD~n commit. You can also run the git status command to check the conflict state.
$ git status
On branch main
You are currently reverting commit 6cb4446.
(fix conflicts and run "git revert --continue")
(use "git revert --skip" to skip this patch)
(use "git revert --abort" to cancel the revert operation)
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: git-revert-file.txt
no changes added to commit (use "git add" and/or "git commit -a")
There are a couple of options to handle the situation.
- If you wish to abort the revert operation run the revert command with the --abort flag.
$ git revert --abort
- You can also use the --skip flag which will skip the commit and proceed with the rest of the sequence.
$ git revert --skip
- You can resolve the conflict and commit the changes.
# First commit #
<<<<<<< HEAD
# Second commit #
# Third commit #
# Fourth commit #
=======
>>>>>>> parent of 6cb4446 (Second commit for git-revert-file.txt)
Once you resolve the conflict run the git add command to stage the changes.
$ git add .
Now run the revert command with the --continue flag to create a new commit with the changes.
$ git revert --continue
[main 6e54848] Revert "Second commit for git-revert-file.txt"
1 file changed, 3 deletions(-)
Different Flags Supported By Git Revert
The git revert command supports a couple of flags.
- The -e or --edit flag will open the external editor to enter the commit message during the revert operation. This is the default behaviour of the revert command and does not need to be used explicitly.
$ git revert --edit HEAD
$ git revert -e HEAD
- The --no-edit flag will not open the external editor for commit. It will create the commit with the default message.
$ git revert --no-edit HEAD
- The -n or --no-commit flag will add the changes to the staging area instead of creating a commit. You must use the --continue flag to commit the changes from the staging area.
$ git revert --no-commit HEAD
$ git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: git-revert-file.txt
$ git revert --continue
Summary Of Commands
This section contains the list of commands used in this guide for your reference.
COMMAND | USAGE |
---|---|
git log --all | List git commit history for all branches. |
git log --all --oneline | List git commit history for all branches but just oneline. |
git revert HEAD | Revert command with HEAD reference. |
git revert | Revert command with commit hash. |
git diff HEAD HEAD~2 | Git diff between two commits. |
git reset --hard HEAD~1 | Remove commit from the commit tree. |
git revert --abort | Abort the revert operation. |
git revert --skip | Skip the revert opertion. |
git revert --continue | Continue the revert operation. |
git revert --edit HEAD | Revert operation with commit message. |
git revert --no-edit HEAD | Revert operation with no commit message. |
git revert --no-commit HEAD | Revert operation with changes added to staging. |
Wrap Up
The git revert command can be used to undo the latest changes. In most cases, you will not use the git revert command to revert to old commits. As foretold in the introduction section, the main advantage of the revert command is your existing commits are not removed and even you can undo the git revert operation using the git reset command.