Squashing Git commits
In Git you can revise your commit history before pushing your changes to a remote repository. This comes in handy whenever you want to group certain changes together, edit commit messages, or change the order of commits.
The golder rule
Squashing commits is an operation which rewrites the history of a git branch, so it should be performed only on a local branch. In other words, never squash commits on a public branch.
Why is it useful?
When using a version control system like git, it’s often considered a good practice to commit early and often. The problem with this approach is that you might end up with a history full of tiny little commits that aren’t really that meaningful by themselves. You can solve this issue by squashing all commits related to a single topic into a single commit, and write a good commit message which explains what you implemented with your changes. If you do so, you’ll end up with a leaner and more meaningful branch history.
Squashing commits is a great way to group certain changes together before sharing them with others.
Let’s imagine that you are working on a particular feature and as soon as you have some meaningful changes (e.g. a function) you would like to commit them. If you have already decided that you will squash some commits later on, you could commit some code without having to worry about writing a good commit message. For example you could write a message like
WIP on new feature, because you know that this message will never make it to the branch history (WIP = Work In Progress). After several “WIP commits” you can squash them together into a single one, and write a good commit message for it.
How is it done?
There isn’t a
git squash command. Squashing commits is an operation which can be performed in several ways by using other commands. I’m aware of 3 ways to do it:
This is the easiest approach. I first heard about this method here. You just have to start with a clean working tree and run
git reset --soft HEAD~X, where
X is the number of commits to squash together.
Let’s make a simple example to see how it works.
After some specific commit (
Initial commit in the image below) you wrote some changes and you committed 3 times. When you wrote those 3 commit messages you just wanted to save your work, maybe because you had to checkout a different branch and fix a bug, or maybe because you don’t like to use
Let’s say that with the 3rd “WIP commit” you have concluded your work on the new feature and you would like to wrap your changes up and start working on a different topic. This is what you should see with
I must admit I’ve never tried this approach. It looks overly complicated and uses a git reset, so it’s probably the riskiest option of the three. Anyway, this is where I found it: