What is git fixup and how it's helpful?

What is git fixup and how it's helpful?

In this blog post, I'll introduce git fixup which is really useful git feature that you can use to keep your project commit history clean. If you are a junior developer or you are already working for quite some time developing applications you've probably been in situations where you worked on bigger features and you made more than a few commits on your feature branch and then you discover that you made a bug and you would like to change the commit in which bug is introduced. If that commit is the most recent one you could use --amend and change that commit, but if the commit you want to change is not the most recent one then you'll have to make a change in the code, commit the change and then interactively rebase commits in order to make your history clean. Here is where git commit --fixup comes handy but let me first show you how you could do that without fixup so that you can see how much easier it is using fixup.

We have a history that looks like this:

* 0b2c830(HEAD -> feature-A) Show error toastr message if user update is not successful
* 812d77a Change text in the Header.js
* c31bb1c Add notification toastr message when update of the user is successful
* 6e8f079 Change hint message in the Home Page
* 260a8a5 Add modal for changing user location address

and let's say that we have a bug in the commit with SHA-1 260a8a5 (the last one) and we want to fix it. After fixing a bug we make a new commit and our history now looks like this:

* 2b10dde (HEAD -> feature-A) Fix save functionality in the modal for changing user location
* 0b2c830 Show error toastr message if user update is not successful
* 812d77a Change text in the Header.js
* c31bb1c Add notification toastr message when update of the user is successful
* 6e8f079 Change hint message in the Home Page
* 260a8a5 Add modal for changing user location address

Now in order to rewrite our git history and to squash commit that has introduced a bug into commit that fixed it, we would have to use rebase interactively.

$ git rebase --interactive HEAD~6

pick 260a8a5 Add modal for changing user location address
pick 6e8f079 Change hint message in the Home Page
pick c31bb1c Add notification toastr message when update of the user is successful
pick 812d77a Change text in the Header.js
pick 0b2c830 Show error toastr message if user update is not successful
pick 2b10dde Fix save functionality in the modal for changing user location

# Rebase 296c8b6..2b10dde onto 296c8b6 (6 commands)

Now once we started interactive rebase we have to move the commit that fixes the bug bellow the one that introduced the bug and then to change pick into fixup or just use the letter f.

pick 260a8a5 Add modal for changing user location address
fixup 2b10dde Fix save functionality in the modal for changing user location
pick 6e8f079 Change hint message in the Home Page
pick c31bb1c Add notification toastr message when update of the user is successful
pick 812d77a Change text in the Header.js
pick 0b2c830 Show error toastr message if user update is not successful

After this, we just have to close the editor and git will do the rest for us after which we'll get a message that refs are updated successfully.

Successfully rebased and updated refs/heads/feature-A.

You can admit that this whole process could take time and repeating all this is not nice, that's why git has introduced git commit --fixup feature. Let's see how using it is much easier than the above process.

The first thing to do once we fix a bug is to stage the changes and then commit them using the following command:

$ git commit --fixup a54b337

After that our history will look like this:

* f5b8829 (HEAD -> feature-A) fixup! Add modal for changing user location address
* e716f2d Show error toastr message if user update is not successful
* 98bc709 Change text in the Header.js
* e8da9ef Add notification toastr message when update of the user is successful
* e1f7672 Change hint message in the Home Page
* a54b337 Add modal for changing user location address

You can notice how git has added fixup! keyword just before the same commit message of the a54b337 commit, and this is how git will be able to move commits on his own once we execute rebase -i --autosquash <commit-sha>~1. <commit-sha>~1 is one commit before the one that we want to fix. So to squash commits we have to use interactive rebase with --autosquash option, and this will rewrite our history with squashing the original commit with the one that fixes the bug into a new commit.

$ git rebase --interactive --autosquash a54b337~1

When we execute this command we will get an interactive editor opened for us:

pick a54b337 Add modal for changing user location address
fixup f5b8829 fixup! Add modal for changing user location address
pick e1f7672 Change hint message in the Home Page
pick e8da9ef Add notification toastr message when update of the user is successful
pick 98bc709 Change text in the Header.js

You can see how git has already rearranged commits for us and all we have to do next is to exit the interactive editor, git will do the rest for us, squashing commit that has introduced a bug into the one that fixed it, leaving us with nice and clean git history.

This is a really good practice if you are working in the team that performs PR reviews, and you can imagine how your git commit history can look like when you add a bunch of new commits which contain small changes in order to fulfill all suggestions that your team members added after reviewing your PR.

I hope that this blog post will help you to understand git commit --fixed feature and that you will use it on your projects. If you are interested in learning more about git check out my ebook git-basics that I published on gumroad. If you don't have an account on gumroad you can register here.