Reverting Changes in Git

We cov­ered revert­ing changes in the sec­tion on git-merge, but let’s dip anoth­er toe in and learn even more about it.

First, let’s review some facts about git-revert and then jump into using it.

When we use git-revert it doesn’t remove the com­mit you are revert­ing from the repos­i­to­ry his­to­ry. Instead, git-revert undoes the changes and cre­ates a new com­mit with those changes undone.

By not remov­ing the com­mit, your his­to­ry of changes is pre­served. As you saw when we revert­ed a revert ear­li­er, this is impor­tant. We want every­thing we’ve done to be ful­ly doc­u­ment­ed in case we ever have to under­stand what hap­pened in the his­to­ry of a repository.

From Linus Tor­valds him­self:

So a revert” undoes the data changes, but it’s very much not an undo” in the sense that it doesn’t undo the effects of a com­mit on the repos­i­to­ry history.

So if you think of revert” as undo”, then you’re going to always miss this part of reverts. Yes, it undoes the data, but no, it doesn’t undo history.

Using git-revert is very help­ful when work­ing on pub­lic or shared repos­i­to­ries because no one is caught by sur­prise by dis­ap­pear­ing com­mits, which is major faux pas when col­lab­o­rat­ing on cod­ing projects.

Prepar­ing for a Revert #

The first thing we want to do before we start revert­ing any changes is to make sure our work­ing tree is clean and clear of mod­i­fied files and uncom­mit­ted changes. 

If there are changes we need to either com­mit them or stash them and then apply the stash lat­er when we’re done revert­ing. Which one we choose real­ly depends on the situation. 

Options for Revert­ing #

We have a few options for how we can revert changes in our repos­i­to­ry. The most basic way to is to revert the last com­mit made.

$ git revert HEAD

We can also spec­i­fy the com­mit we want to revert:

$ git revert 4189c8d4

When the revert hap­pens, Git auto­mat­i­cal­ly cre­ates a new com­mit that undoes the changes of the com­mit we are revert­ing. We can tell Git not to cre­ate the com­mit but just stage the changes that undo that com­mit by using the --no-commit switch.

$ git revert --no-commit 4189c8d4

We can also spec­i­fy a num­ber of com­mits back before HEAD to revert, with­out spec­i­fy­ing the actu­al com­mit hash.

git revert HEAD~2

This will revert the changes in the third last com­mit — HEAD + 2 — and cre­ate a com­mit undo­ing those changes. Be care­ful using this one because you’re not spec­i­fy­ing a com­mit hash and there’s a chance you could mis­count and reset the incor­rect com­mit (but since all reverts are com­mit objects, we can revert a revert!).

If you have more than one com­mit range to revert (uh oh some­one is in trou­ble if that hap­pens!), you can do that using this syntax:

git revert my_feature_branch~5..my_feature_branch~2

This will revert the changes in the my_feature_branch from the fifth last com­mit to the third last com­mit, includ­ing those fifth last and third last com­mits. This ver­sion of the com­mand, how­ev­er, does not auto­mat­i­cal­ly cre­ate a com­mit undo­ing those changes. It only changes the work­ing tree and index.