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 HashComment
47c644bfile5A
9f6883ffile4A
705bdb0file3
dd02423file2
b8140c2file1

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

git reset --hard 705bdb0

Effectively this will remove the unwanted commits and leave you with the following revised git log.

Commit HashComment
705bdb0file3
dd02423file2
b8140c2file1

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:

git revert HEAD~1^..HEAD

This will create two new commits and leave us with the following git log:

Commit HashComment
023b4efRevert "file4A"
e7766f5Revert "file5A"
47c644bfile5A
9f6883ffile4A
705bdb0file3
dd02423file2
b8140c2file1

Alternatively you can list out the commit hashes like so:

git revert 9f6883f^..47c644b

Reverting just a single commit is even simpler:

git revert [Commit Hash]

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.