Reverting Back Changes in Git
In this tutorial, we will show you how to revert back changes with Git, including …
- discarding changes made in your working directory
- unstaging changes made in the staging index
- amending a commit
- checkout a previous version
- git revert
- git reset
If you want to follow along, set up your Git directory as indicated in previous tutorial.
Discarding Changes in Working Directory
Suppose we make an change to the file index.html in our working directory. Git status shows that we have a modified change…
It even give us a hit to use “git checkout — <file>…” to discard changes in working directory.
So now if we want to revert back our index.html to its original, and in particular back to the version that is in the repository, we do ….
git checkout — index.html
Doing a git status now will show no modified file and nothing to commit. Examining the index.html content, you will find that our change had be removed and put back to original.
In this case, the command …
git checkout index.html
would have also worked, but best practice is to use the double dash when using checkout to revert changes (as opposed to switching branches). See why the double dash in git checkout.
Unstaging Changes
But what if you have already made a change to the index.html file and added it to the staging index via the git add command…
git add index.html
Now a git status shows that …
It gives the hint to use “git reset HEAD <file>” to unstage. So to revert the index.html in the staging index back to original, we do …
git reset HEAD index.html
This resets the staging index copy to the version that is pointed to by the HEAD pointer, which is the version at the tip of the current branch in the repository. Since the stage copy would be the same as in the repository, it is taken out of the staging index. But the working copy still has your changes.
This technique is also known as unstaging a file in GIT.
Amending a Commit
But what if you had already committed the changes to the repository, such as with the command …
git commit -a
which adds and then commits all changes (but not additions and deletions) from the working directory to the local repository, bypassing the staging index.
You can only amend the very last commit (and only before another person makes another commit to the same file).
You fix the index.html file in the working directory and then add to staging index…
git add index.html
And then do an git commit –amend as in …
This commit takes what is in the staging index and combines it with the previous commit and replaces it. If you only want to change the commit messages, then you amend the commit with a new message without staging anything.
You can do “git log” to see that the previous commit was replaced.
You should not amend commits that others have seen or based work on already. The Atlassian tutorial writes …
“If you amend a commit that other developers have based their work on, it will look like the basis of their work vanished from the project history. This is a confusing situation for developers to be in and it’s complicated to recover from.”
Checkout a Previous Version
If you have made a commit and can not or do not want to do an amend. You can checkout the previous version of the index.html file into your working directory and make a new commit.
To checkout a previous version, do a “git log” and checkout the version with the SHA specified as in …
git checkout 2e0c8bdfdkf — index.html
You can specify the entire SHA, but only a partial SHA will often work.
The double-dash indicates that we are not switching branch. This checkout will revert back the working copy to the previous version and will also stage it.
git revert
Let’s say commit 76d76c was a mistake and you want to undo it, you can revert it by …
git revert 76d76c
It will undo the changes of commit 76d76c. Your working copy will be revert back. And a new commit made — all in one shot. It will prompt you for the commit message
Note that we specify the SHA of the commit that we want to undo (not the SHA that we want to revert to).
But sometime it fails to perform the commit because of merge conflicts…
You would then have to resolve the conflicts in the working copy of index.html …
Add to staging index and make the commit.
git reset
These commands are getting more and more powerful. Use “git reset” with caution and do not use it on commits that other developer may have seen or based work off of.
git reset moves the HEAD pointer with three possible options…
- –soft – resets HEAD pointer but does not change staging or working copy
- –mixed – resets HEAD pointer, change staging index to match repository, but no change to working copy.
- –hard – resets HEAD pointer, change staging index and working copy to match.
The default is “mixed” in which case we do …
which is equivalent to …
git reset –mixed 2e0c8b
The git status will show that there are changes in our working tree that are not staged…
That is because our stage copy has been reverted. At this point, you can add the working copy to stage for commit. Or revert back your working copy to match stage with “git checkout — <file>”.
There is also the –merge and –keep option, which are beyond the scope of this tutorial.