Reverting Changes in Git
We covered reverting changes in the section on git-merge, but let’s dip another 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 commit you are reverting from the repository history. Instead, git-revert
undoes the changes and creates a new commit with those changes undone.
By not removing the commit, your history of changes is preserved. As you saw when we reverted a revert earlier, this is important. We want everything we’ve done to be fully documented in case we ever have to understand what happened in the history of a repository.
From Linus Torvalds himself:
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 commit on the repository 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 helpful when working on public or shared repositories because no one is caught by surprise by disappearing commits, which is major faux pas when collaborating on coding projects.
Preparing for a Revert #
The first thing we want to do before we start reverting any changes is to make sure our working tree is clean and clear of modified files and uncommitted changes.
If there are changes we need to either commit them or stash them and then apply the stash later when we’re done reverting. Which one we choose really depends on the situation.
Options for Reverting #
We have a few options for how we can revert changes in our repository. The most basic way to is to revert the last commit made.
$ git revert HEAD
We can also specify the commit we want to revert:
$ git revert 4189c8d4
When the revert happens, Git automatically creates a new commit that undoes the changes of the commit we are reverting. We can tell Git not to create the commit but just stage the changes that undo that commit by using the --no-commit
switch.
$ git revert --no-commit 4189c8d4
We can also specify a number of commits back before HEAD to revert, without specifying the actual commit hash.
git revert HEAD~2
This will revert the changes in the third last commit — HEAD + 2 — and create a commit undoing those changes. Be careful using this one because you’re not specifying a commit hash and there’s a chance you could miscount and reset the incorrect commit (but since all reverts are commit objects, we can revert a revert!).
If you have more than one commit range to revert (uh oh someone is in trouble if that happens!), 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 commit to the third last commit, including those fifth last and third last commits. This version of the command, however, does not automatically create a commit undoing those changes. It only changes the working tree and index.