How to Squash Commits in Git
To "squash" in Git means to combine multiple commits into one. You can do this at any point in time (by using Git's "Interactive Rebase" feature), though it is most often done when merging branches.
Please note that there is no such thing as a stand-alone git squash
command. Instead, squashing is rather an option when performing other Git commands like interactive rebase or merge.
The Git Cheat Sheet
No need to remember all those commands and parameters: get our popular "Git Cheat Sheet" - for free!
When to Squash Your Commits
As already said, the act of "squashing" your commits means that you combine multiple existing commits into a single one. If you should do this or avoid it is - to some extent - a question of preference: in some teams, for example, squashing commits is the preferred way to merge a feature branch back into a long-running branch like "master" or "main".
But why exactly would you do this? Let's take the classic case of a feature development as an example: you have probably worked on a separate feature branch and produced a number of commits in this context. Depending of the complexity and duration of your work, it might even be quite a high number of commits. At some point, you will want to merge your work back into the main branch. This is typically when you decide to squash or not:
- (a) if you decide to squash before merging, then all of those individual commits from your feature branch will be combined into a single commit. The main commit history, therefore, will only show a single commit for this integration.
- (b) if you decide AGAINST squashing, all of your individual commits will be preserved as such.
Some teams see a possible advantage in going with (a) and using squash: instead of many individual commits which might be unnecessary and potentially overwhelming, only a single commit appears in the main commit history. This can be helpful in keeping things orderly!
However, you cannot say that (a) or (b) is the "correct" way of doing things. There are pros and cons to both approaches, so it's mostly a matter of preference and convention.
How to Squash Your Commits
There are different ways and tools when it comes to squashing commits. In this post, we'll talk about Interactive Rebase and Merge as the two main ways to squash commits.
Interactive Rebase
You can manually squash your commits at any time using Git's "Interactive Rebase" feature. Going deep into Interactive Rebase goes beyond the scope of this article (take a look at the First Aid Kit for Git for a series of free, short videos on this topic), but we'll walk through a simple example case together.
Let's say you have completed your work on a new feature branch (in the below example "feature/login") and now want to merge it back into the "main" branch. But before doing so, you'd like to clean up and squash the new commits into a single one:
We can do so by starting an Interactive Rebase session:
$ git rebase -i HEAD~3
An editor window will then open where you can choose how you want to manipulate the selected part of your commit history. Keep in mind that Interactive Rebase allows to perform many different actions on your commit history; for our example case here, however, we are interested in the "squash" action keyword. If you mark one or more lines as "squash", they will be combined with the one above:
After entering a commit message for the new, combining commit, the Interactive Rebase is completed - and the three old commits have been squashed into one.
Tip
Using Interactive Rebase in Tower
In case you are using the Tower Git client, using Interactive Rebase to squash some commits is very simple: just select the commits you want to combine, right-click any of them, and select the "Squash Revisions..." option from the contextual menu.
Merge
Squashing is also an option when merging branches:
$ git merge --squash feature/login
Auto-merging imprint.html
Removing img/iconBlog.png
Auto-merging about.html
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
The effect is very similar to what we've discussed before: all changes will be combined just as with a normal merge - but by using the --squash
option, instead of a merge commit being automatically created, you're left with local changes in your working copy which you can then commit yourself.
In the end, this allows you to avoid the automatic commit that typically happens as a result of a merge. It will appear as if the work for your feature had happened in just a single commit.
Pull Requests
This strategy - using squash when merging - is often used when a Pull Request is closed. Code hosting platforms like GitHub, GitLab, or Bitbucket support this as an option when merging a Pull Request:
Learn More
- Check out the First Aid Kit for Git, a free series of of short videos about Interactive Rebase and other Git tools for undoing mistakes
- More frequently asked questions about Git & version control