How to Git Squash Commits?

Writing git commit is hard, to speed things up sometime we just write small commit and push the changes. But sometime if we look back the commit message we just got the idea to clean up the commit message. Luckily there's a feature on git that let you do that.

Squash Commits

You might write small commit message like this.

git add .
git commit -m "docs: update readme"
git push

This is example git commit history of one of my git repository.

git log --oneline

1e3c6d1 doc: update readme
07df308 doc: update readme
9372264 doc: update logo
59e1df2 doc: update logo
122be6a doc: update logo

Git Rebase

In this case is better to merge two or more commit into one commit since they are have the same message. So for that we can do squash commit. Here's how you can do that.

git rebase -I HEAD~5

This git command will pick the last 5 commits and then we can do squash commit. If you run that command it will display this message.

pick 1e3c6d1 doc: update readme
pick 07df308 doc: update readme
pick 9372264 doc: update logo
pick 59e1df2 doc: update logo
pick 122be6a doc: update logo

# Rebase 1e3c6d1..122be6a onto 85f6cdb (10 commands)
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
# These lines can be re-ordered; they are executed from top to bottom.
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted

As you can see there's several operation that we can use to manipulate the commit message.

pick 1e3c6d1 doc: update readme
fixup 07df308 doc: update readme
pick 9372264 doc: update logo
fixup 59e1df2 doc: update logo
fixup 122be6a doc: update logo

So in this case we want to delete duplicate commit so we use fixup operation. And the commit will be like this.

1e3c6d1 doc: update readme
9372264 doc: update logo

After doing squash commit we need to force push since it updating the commit history, it like delete the commit history.

git push origin main --force

Yeah that's how you can clean up your commit history, see you in the next article.