Song of the Week
Introduction
Last week we covered how to do a hard reset of your repository. Though they're sometimes necessary, hard resets are a pretty destructive method of rewinding your repository because they alter the commit history.
Today's post will cover the nondestructive rewind, aka git revert
.
We'll go over:
- What
git revert
does and how it is different fromgit reset
. - How to revert a single commit.
- How to revert a range of commits.
Git Revert vs Git Reset
The git revert <commit-hash>
command will reverse the changes made by the commit hash given, and then create a new commit. This is the preferred method for undoing the changes of a specific commit if that commit has already been push to a shared remote repository because it preserves the commit history.
This is different from a git reset
, because a reset will move the HEAD ref to the commit hash given, and drop all the commits after that one. A git revert
only reverses the commit that was given and keeps all the following commits and the changes that were made in them. This makes git revert
great for removing a bug that was introduced by a single commit without having to redo all the work in the following commits.
How to Revert a Single Commit
To revert a single commit, enter the following git command in the terminal:
git revert <commit-hash>
You can also pass git revert
a reference to the commit that is relative the HEAD ref. So, if you entered git revert HEAD~2
, the changes from the third most recent commit would be reversed.
Let's look at an example. I created a local repository with some files whose names match the commit in which they were created, which looks like this:
All these files just have the text "added content" in them and each was added with their own commit. The git log
looks like this:
Now let's say there was some bug in commit A that we wanted to undo but keep commits B-D. We would enter the following git command:
You can see in the git log
that the git revert
command automatically created a commit. Also, I used HEAD~3
to reference commit A. Remember that most recent commit is equal to HEAD
, which can be written as HEAD~0
. So, the fourth most recent commit is HEAD~3
.
Now if we look at the working directory you'll see that the "commit-A" has been removed, but the rest remain.
How to Revert a Range of Commits
To revert a range of commits, simply enter the following git command in the terminal:
git revert -n <commit-hash>^..<commit-hash>
Notice the ^
before the two periods. That caret symbol tells git to include that first commit hash given in the range. And the -n
option tells git to not create a commit, but to instead stage the changes in the Staging Index and the Working Directory. This way you can do one commit manually to maintain a neat commit history.
In the same example we used above, lets say we want to rewind to commit A and maintain the commit history. You could do that like this:
By running git status
, we can see that all files added in the commits B-D have been deleted.
Now we just need to commit those changes.
In the git log
we see that commits B-D are still in the commit history even though their changes have been reversed.
If we open the Working Directory, we'll see that it has indeed rewound back to commit A.
Takeaways
-
git revert <commit-hash>
will reverse the changes made by the commit hash given, and then create a new commit. - Unlike
git reset
,git revert <commit-hash>
will not remove the commits after the commit given, thereby preserving the commit history. -
git revert
will also accept a commit reference based on HEAD, likegit reset HEAD~3
, for example. -
git revert -n <commit-hash>^..<commit-hash>
will reverse the changes by the range of commits given(inclusively), and will stash the changes in the Staging Index. The-n
option prevents the auto commits, so you will need to do a manual commit.
References
Cover Image - Mt St Helens
Git Revert - atlassian.com
Git Revert - Git Docs
How to revert multiple git commits? - stackoverflow.com
Top comments (0)