Git revert and Git reset allow you to “go back” to different commits in your commit history. Say the last 5 commits you made are no good. You can “reset” back to 5 commits ago, or you can “revert”. The problem with reset is that it’s destructive. It will wipe the commits off the face of the planet. This is especially no good if you’re working on a public repository.
So instead of git reset, I’ll almost always use git revert, which keeps the un-wanted commits around, but still gets you back where you want to be. Let’s look at a fancy diagram to make it easier…
Okay let’s give this a shot… Go ahead and follow along with the steps below:
- Create a project directory:
$ mkdir revertTest
- cd into folder:
$ cd revertTest
- create file with contents:
$ echo "commit 1" >> test.txt
$ git init
- commit file:
$ git add .
git commit -m "commit 1"
- Make a total of THREE commits:
- $ echo “commit 2” >> test.txt
- git add .
- git commit -m “commit 2”
- echo “commit 3” >> test.txt
- git add .
- git commit -m “commit 3”
Okay, we’re ready. My text editor has three lines. Each added by a different commit:
My command line looks like this. Pay attention to your commit numbers, as they’ll probably be different than mine:
Say you want to go back multiple commits… All you have to do is identify the hash of the commit you want to “go back to”, and run git revert using the following formula:
$ git revert --no-commit hashNumber..HEAD
Since I’m trying to get back to the commit “253d587”, then I will run this command:
$ git revert --no-commit 253d587..HEAD
Now if you look at your text editor you’ll see the text is back to “commit 1” only, which means we’ve moved back to commit 1! Now we have changes in our file history that need to be committed. You can do that like regular, but you’ll want the commit message to explain that you’ve gone back to a different point in history.
$ git commit -m "revert to commit 1"
In the image below you see both my project directory with the contents of the first commit only, as well as all the history of the project.
So what’s actually happening? Basically git is walking backwards from the current commit to the commit before it… One at a time and “undoing” the changes at each commit until it reaches the commit you specified. The no-commit flag prevents git from providing a commit message for each step. If you were to revert 10 commits without the no-commit you would clutter up your commit history and make it harder to understand.
Once the specified commit has been reached Git stops. Because there were file changes made you’ll have staged changes ready to be committed. You can then leave a commit message like “Reverted to commit X”.
What is HEAD though?
Head is easiest to think of as the “pointer” to your last commit on the branch you’re currently on. It’s basically the “most recent commit”. Here’s an SO post for more details.