Clean up your Git history

Reading time ~7 minutes

We all like to keep our code looking as neat as possible, but sometimes you also need to keep track of those small changes you’ve been making. A good way to ABC (Always Be Committin’) is to work in a branch and hack your way through the problem and then to clean up before submitting a PR.

Cut a new branch

What we are about to do here can be destructive as well as confusing. With tasks like that, it’s always nice to have a backup and so we are going to cut a new branch to work with off of the branch that all of the nasty more changes live in:

git checkout -b squashed_feature

Rebase from master

This will give us a branch that we can then safely rebase from master. This process will allow you to pick the commits you would like to squash and the ones you would like to keep. You can do this by running:

git rebase -i master

Squash commits

If you have merged master into your branch during your development process you will be unable to use this method. I normally will rebase my branch on master instead of merging in, but workflows may vary. Once you begin the rebase process, your git editor will open a file that looks like:

pick 3e33836 Initial commit of consul-template role
pick 7a09b99 remove boilerplate
pick 935e5e4 Default openssl.cnf
pick 6277156 Add all ips as SAN
pick 8cc1e89 Add SAN IP to certificates
pick e5aa77c Have to repro with hosts
pick 9819551 Change from 5 to 3 dockerhosts to reduce time

# Rebase d33881f..9819551 onto d33881f
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# 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.
#
# Note that empty commits are commented out

In this view the most recent commit will be at the top and the oldest at the bottom. To squash all of the commits into a single one, change all the ‘pick’s but one to ‘squash’. Note: ‘s’ will also work instead of ‘squash’

pick 3e33836 Initial commit of consul-template role
s 7a09b99 remove boilerplate
s 935e5e4 Default openssl.cnf
s 6277156 Add all ips as SAN
s 8cc1e89 Add SAN IP to certificates
s e5aa77c Have to repro with hosts
s 9819551 Change from 5 to 3 dockerhosts to reduce time

...

Rewrite

You want to squash these changes as if you were to remove the line itself, the actual commit will be removed from history:

# This is a combination of 7 commits.
# The first commit's message is:
Initial commit of consul-template role

# This is the 2nd commit message:

remove boilerplate

...

At this screen there is no need to change the commit messages. After saving and quitting the editor, a new file will open to allow you to edit the commit message. In that file, just remove all of the messages and replace them with the one that you want.

You can now push your branch up and open a PR!

git push origin squashed_feature

Source

Update from Matt

Matt has been working on big art recently, including Double Diamond and Moonrock Mountain. They are both large-scale sculptures that incorporate everything he has learned throughout his career. Continue reading