How to Squash All Commits Related to a Single Issue into a Single Commit

Updated Sep 3, 2020

This article outlines how to use the “squash” feature of an interactive git rebase.

What does “squashing” do?

It allows you to take changes that are spread amongst multiple commits and consolidate them into one.

Why should one consider squashing commits?

  • A clean history makes tracking changes to a large codebase across time much easier.
  • Many commits are small and unimportant in the grand scheme to keep as standalone commits. Example: “Fix documentation spelling mistake”

How to squash commits

To squash multiple commits into one in the branch you’re on, do the following:

  • Run git log to determine how many commits to squash. Let’s assume 4.
  • Run git rebase -i HEAD~4 (with 4 being the number of commits)
  • OR
  • Run git rebase -i [SHA] (where [SHA] is the commit after the last one you want to squash. *)
  • You should see a list of commits, each commit starting with the word “pick”.
  • Make sure the topmost, first commit says “pick” and change the rest below from “pick” to “squash”. This will squash each commit into the previous commit, which will continue until every commit is squashed into the first commit.
  • Save and close the editor.
  • It will give you the opportunity to change the commit message. What you see is a single message containing all of the commit messages. Edit these as you wish.
  • Save and close the editor again.
  • Important: If you’ve already pushed commits to origin, and then squash them locally, you will have to force the push to your branch. - git push origin branch-name --force (note that you can use -f instead of --force.)

* What if you want to squash and include the first commit? use git rebase -i --root. Documentation

Let’s go over a complete example.

Process overview

We finished some feature branch work that we want to merge into master. We accidentally left out the ticket number, the messages aren’t so clear, and we don’t need the error fixing work in its own commit:

$ git log

commit 111111111111
    improve parsing function
commit 222222222222
    fix regex error in object file
commit 333333333333
    test that crazy bug case
commit 444444444444
    etc

We put in a pull request, get it approved and decide to squash all the commits into one. We run the command git rebase -i 444444444444 at our terminal.

After going through the whole process outlined above, our result commit is:

[JIRA-535] Fix that crazy bug:

- break parsing function into smaller functions
- test that crazy bug case

We can breathe easier; the messaging in this single commit will help future developers understand and find the work more easily.

Now, imagine looking at this tidy commit list on the master branch:

[JIRA-523] Fix that crazy bug:
[JIRA-535] Put in UI feature:
[JIRA-514] Get data from API:
[JIRA-125] Upgrade dependency:
[JIRA-567] Homepage accessibility:
...

Happy squashing 😁

Related posts

Formatting commit messages with Conventional Commits

Resources

How to set up Visual Studio Code as your git editor

https://code.visualstudio.com/docs/editor/versioncontrol#_vs-code-as-git-editor