Git Revert: A Safe Way to Remove Faulty Commits
Gaurav Singh
Posted on September 29, 2024
Have you ever faced a situation where you had to undo changes in the master branch because some unwanted code was committed, potentially leading to production bugs?
Well, we faced a similar issue in our project when a developer accidentally cherry-picked a commit that wasn’t tested and deployed it to production. Luckily, our app is an in-house product used by the company itself, so the impact was minimal.
Such cases can happen when you have a distributed team spread across a few countries and different time zones. Here's how we removed a particular commit from our master (production) branch and resolved the issue quickly.
Git revert to the rescue.
git revert
is used to create new commits that reverse the effects of earlier commits (often just a faulty one).
The git revert
command can be considered an "undo" type of command, but it is not a traditional undo operation. Instead of removing the commit from the project history, it inverts the changes introduced by the commit and appends a new commit with the resulting inverse content. This prevents Git from losing history, which is crucial for the integrity of your revision history and for reliable collaboration.
In simple terms, git revert
is used to undo a commit (say hash 2afe34
), but it does so by creating a new commit that removes the changes from the commit (2afe34
) you are reverting.
For example, if you’re tracking down a bug and find that it was introduced by a single commit, instead of manually fixing it and committing a new change, you can use git revert to automatically handle this for you.
Syntax:
git revert [--options] <commit>
git revert
takes a specified commit from the history, inverts the changes from that commit, and creates a new "revert commit."
Let's demo it:
I have this index.html file I created for demo purposes. It contains an ordered list of fruits. Below are my commits with the changes made in each one:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Fruits</title>
</head>
<body>
<div>
<h3>Fruits list</h3>
<ol>
<li>Mango</li>
<li>Orange</li>
<li>Banana</li>
</ol>
<h3>Other list</h3>
<ul>
<li>Apple</li>
<li>Pineapple</li>
</ul>
</div>
</body>
</html>
7afe5e3 (HEAD -> master) add other list
c8862d9 add banana
8db1cd2 add orange
f4e9e1f add mango
065a354 initial commit
My first commit is an initial commit with just the basic HTML structure like head and body. Rest commits are self explanatory. I added mango in commit f4e9e1f
, orange in 8db1cd2
, and banana in c8862d9
inside the first ordered list (<ol>
). I then added a second ordered list with more items in commit 7afe5e3
, which is the current HEAD commit.
Let’s say I want to remove banana from the list. In this simple example, we could just remove banana from the code and create a new commit reflecting that change.
However, in a collaborative project with multiple contributors, commit history becomes important to track the project's state at any given point in time. Moreover, manually undoing large code changes wouldn’t be feasible, and git revert becomes an inevitable solution.
Going back to our demo, to remove banana from the first ordered list, I can simply run git revert c8862d9
and this creates a new commit explaining the reason for the revert. You’ll see that banana is now removed from the list.
So new index file and commit history will look like below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fruits</title>
</head>
<body>
<div>
<h3>Fruits list</h3>
<ol>
<li>Mango</li>
<li>Orange</li>
</ol>
<h3>Other list</h3>
<ul>
<li>Apple</li>
<li>Pineapple</li>
</ul>
</div>
</body>
</html>
Commit history after git revert: git log --oneline
828ef17 (HEAD -> master) Revert "add banana"
7afe5e3 add other list
c8862d9 add banana
8db1cd2 add orange
f4e9e1f add mango
065a354 initial commit
Sometimes, Git is not smart enough to figure out the exact code that needs to be removed, leading to merge conflicts. In these cases, you, as a developer, need to help Git a bit.
It’s important to understand that git revert
undoes a single commit—it does not "revert" the project to a previous state by removing all subsequent commits like git reset
.
Reverting has two important advantages over resetting:
It doesn’t change the project history, making it a “safe” operation for commits that have already been published to a shared repository.
git revert can target an individual commit at any arbitrary point in the history.
Happy coding! 😊
Posted on September 29, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.