Top 3 git commit history issues and how to solve them simply and quickly
This is it. The moment has come. The big feature that you have worked on for the past few months, and the company has planned for the past few years, has finally been finished. You take a small sip of champagne. Then you get a call from the tech lead. Your git commit history is all messed up. You leave the champagne glass in a hurry and take a long hard look. You break down the issues:
Issue #1: Your last commit contains typos and you would like to reword it
The feauture has been fuly completed

It is not unusual after you have worked long hours on a project to find typos in your commit history. Thankfully, the fix here is straightforward. In the root directory of the project in your CLI type:
git commit --amend
This will open up an editor that will allow you to change the message of your last commit. Alternatively, you can do the message change in a single line:
git commit --amend -m "The feature has been fully completed"
Issue #2: You see dozens of commits that are in the git commit history of your branch.
Your project is already looking better now that you have updated the last commit message. However, after you have merged the latest changes from master, you see some changes that have nothing to do with your work. The files changed have jumped from 6 to 24 but you have not worked with 24 files. There are several fixes for this. For both of them, you need to determine how many commits (in reverse order) you would like to select.

Approach #1: Remove any unwanted commits
If you only want to keep the commits you have made but not the ones made by other developers, you can remove the unwanted commits. The following commands will save the last 4 commits (stash), remove all other unwanted commits between master and your 4 commits, and then recommit the 4 commits you saved (stashed). In the root directory of your project in your CLI type:
git reset --soft HEAD~4
git stash save "feature branch commits"
git reset --hard master
git stash pop
git commit -m "The feature has been fully completed"
git push -f origin feature
Approach #2: Interactively rebase to rewrite, replace, delete, and merge individual commits.
If you would like to choose which individual commits should be changed, you can use the git rebase -i
(shorthand for git rebase --interactive
). In the current case, we will select 4 commits:
git rebase -i HEAD~4
This will open an editor with a list of commits that we would like to be changed. It is worthwhile to mention that the commits are in an opposite order with the most recent one listed at the bottom. See the following section for an explanation of the rebase commands.
pick 06b4bfg The MVP has been built
drop dea3n45 Something built by another dev
drop 3bg4nf3 Another thing thing built by another dev
pick ef45e34 The feature has been fully completed
Issue #3: You would like to squash several commits into a single one
You have committed quite a few times in your project but realise that you only want a single commit at the end. If you only want to keep the changes in your project but not the actual commits that led to these changes, you can squash everything into a single commit. Either use squash or fixup to merge selected commits into the previous ones, which are used. The subtle difference between squash and fixup is explained below.
fixup 06b4bfg The MVP has been built
fixup dea3n45 A bug has been fixed
fixup 3bg4nf3 The code has been cleaned up
pick ef45e34 The feature has been fully completed
Options
When we are in vim, we select a commit with arrow ↑ and arrow ↓ and press i. After we are done we press ESC and type wq
in the Vim editor to save and quit.
- Pick
Pick is the default option set for each commit. It means that the selected commit will be used.
- Squash
The squash option will allow us to specify, which commits we would like to merge into the previous commits. This will open a prompt in the terminal to write a combined message for the squashed commits.
- Fixup
The fixup option is similar to the squash option but discards the commit’s message. Instead, the previous commit’s message will be used.
- Drop
The drop option allows us to remove a commit. This provides us with an unambiguous option for deleting any unwanted commits from within a history of other commits.
- Other Options
While these options are not used in our examples, git rebase --interactive
allows other options that I would like to briefly mention. The reword option uses a commit but opens up a prompt for us to edit the message of the selected commit. The edit option does what it says, it uses the commit but allows it to be amended.
It is important to resolve any conflicts that may occur from the rebase in your editor. After they are resolved likely more conflicts will need to be resolved. In our CLI, we will use the git rebase — continue command until every conflict is fully resolved.
Finally, we will need to push to our fork. Since history has changed and git forbids to modify the history of the remote, we need to force push. However, it is important to note that if your teammates have committed to the remote branch but your local branch does not have these commits, force push will delete their commits (use at your own risk). This is not the case in our scenario. Therefore, in our CLI we type:
git push -f origin feature
When you are programming on a relatively big project, a moment comes where you may have committed the wrong GitHub message, or your branch may contain commits that you would like to remove or meld (combine) several commits in one. The approaches above provide us with the tools to tackle these situations in order to achieve a clean commit history.
You can now take a bigger sip of the champagne. 🍾🥂
This article was written by Rosen Toshev, Software Developer at Expend. If you’re tired of emailing receipts to your boss and chasing them to pay expenses, check out Expend’s all in one expense management and smart card solution. We’re also hiring for multiple technology roles, come join us as we seek to automate and simplify expenses🚀