In this post I will show a few examples of how you can use Git to undo mistakes in your code base.
Fixing Mistakes
Whenever you make a mistake in your codebase, the typical workflow for fixing the mistake is to make an additional commit to correct the issue introduced by a previous commit. Most of the time this is the appropriate solution, especially in cases where you want to keep the majority of the changes in the previous commit.
However there are cases where rolling back a feature by manually removing all changes can be impractical. In the following sections I will show a few Git techniques that will allow you to roll back changes at the commit level.
Reset
Git reset is a powerful command that allows you to reset to an arbitrary point in your Git history. In cases where you are the last person to push to master, reset can be an appropriate way to shed unwanted commits at the end of your Git history.
Let’s look at my sample Git history below:
Commit Hash | Comment |
47c644b | file5A |
9f6883f | file4A |
705bdb0 | file3 |
dd02423 | file2 |
b8140c2 | file1 |
Let’s assume we have just learned that commits 47c644b and 9f6883f were made in error and are causing problems in the repo.
The team agrees that reverting back to commit 705bdb0 will fix the issue, so we run the command
Effectively this will remove the unwanted commits and leave you with the following revised git log.
Commit Hash | Comment |
705bdb0 | file3 |
dd02423 | file2 |
b8140c2 | file1 |
Problem solved! Well almost. We still need to update origin/master with these changes. A regular push won’t do since we will get an error message saying that the local branch is behind the remote branch after removing two of the commits.
Another thing that won’t work is to do the revert in a branch from master and make a PR back to master. In that case there will be nothing to PR since the new branch with the reverts doesn’t contain any changes that are not already in master.
The solution is to force push to master using the --force flag. At this point it’s important to notify the team that you are about to force push since this will potentially cause merge conflicts and undo any changes made to master since you last synched. Because of the potential for issues you should be very careful when force pushing to master.
Revert
Revert can be a safer approach to rolling back changes since it doesn’t remove the commits. Instead it creates new commits to undo the the unwanted commits. In principle this is similar to manually fixing the issue, except you leverage Git to create new commits instead of doing it manually.
To revert the two most recent commits in my sample I run the command:
This will create two new commits and leave us with the following git log:
Commit Hash | Comment |
023b4ef | Revert "file4A" |
e7766f5 | Revert "file5A" |
47c644b | file5A |
9f6883f | file4A |
705bdb0 | file3 |
dd02423 | file2 |
b8140c2 | file1 |
Alternatively you can list out the commit hashes like so:
Reverting just a single commit is even simpler:
When using revert you don’t have to force push since the revert commits are just like regular commits. The only downside is that your Git commit history will continue to include the unwanted commits.