Data report"State of code review 2024" is now liveRead the full report

How to squash Git commits

Greg Foster
Greg Foster
Graphite software engineer


Note

This guide explains this concept in vanilla Git. For Graphite documentation, see our CLI docs.


Git squash refers to the process of combining multiple commit messages and changes into one. This is usually done via an interactive rebase, which allows you to consolidate commits in a way that maintains a clean and understandable project history.

Squashing commits in Git lets you streamline your commit history, combining multiple commit entries into a single, cohesive commit. This process is particularly useful for cleaning up your history before merging a feature branch into the main branch.

This guide will cover how to effectively squash commits using various git rebase commands.

Before squashing, ensure your working directory is clean. It's recommended to commit or stash your changes to avoid losing work during the rebase process.

For an in-depth guide on how to stash your commits, see How to use git stash.

Once your local work is safely stashed away, it’s also helpful to run git log to view the current state of your commit history. This will allow you to find the commits that you want to squash into each other.

  1. Start an interactive rebase session: Determine how many commits you want to squash. For example, to squash the last 3 commits:

    git rebase -i HEAD~3

    This command will open an interactive editor with a list of the last 3 commits from the current branch.

  2. Pick and Squash Commits: In the editor, you'll see each commit prefixed with pick. To squash commits, change pick to squash (or s for short) next to the commits you want to combine. Leave the first commit in the list as pick, which will be the commit all others are squashed into.

    pick e3a1b35 Add feature x <---- Initial commit squash 4f3c4d2 Update feature x squash a5b6c7d Fix typo <---- Most recent commit

    Here it’s useful to squash all of these commits into the initial commit because the other don’t offer standalone value. We don’t need a separate commit showing that we “fixed a typo”. It’s much more useful to look through the commit history and see that feature x was added.

  3. Create a new commit message: After saving and closing the editor, Git will prompt you to create a new commit message for the squashed commit. Follow the instructions in your editor to finalize the commit message.

As an example, this is what you might see in the terminal output and editor, after squashing the features we just looked at in the previous section.

Terminal
In the editor for the commit message, you will see a pre-populated message including all the commit messages of the commits that are being squashed, like so:
```
# This is a combination of 3 commits.
# This is the 1st commit message:
Add feature X
# This is the commit message #2:
Update feature X
# This is the commit message #3:
Fix typo in feature X
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Detached HEAD state at d2c2955
# You are currently editing a commit while rebasing branch 'feature-branch' on 'd2c2955'.
#
# Changes to be committed:
# modified: file1.txt
# modified: file2.txt
#
```

At this point, you can edit the commit message for the new, squashed commit. We can eliminate the messages for the update and typo fix.

Terminal
Implement feature X
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
...

Here we deleted the other commit messages, and kept the most important one: Implement feature x. After saving and closing this file, Git completes the squash, applying the new commit message to the squashed commit. Your terminal might not show much immediately after, but running git log would show the new commit history with your squashed commit at the top.

To squash all commits in your feature branch into a single commit:

  1. Determine the base commit or the point where your branch diverged. This can be done with git merge-base or visually with git log --graph.

  2. Start an interactive rebase for all commits on your branch:

    git rebase -i <base-commit>

  3. In the editor, change all commits except the first to squash or s, then follow the prompts to create a new commit message.

  • Squashing commits that have already been pushed: If you need to squash commits that have already been pushed to a remote repository, follow the same process but use git push --force to update the remote repository after squashing. This typically should be done on a feature branch, prior to merging the branch into main. If force pushing to main, make sure to communicate with your collaborators first.

  • Creating a new branch with squashed commits: If you want to preserve the original commits on your current branch, create a new branch and squash commits there:

    git checkout -b new-branch-name git rebase -i HEAD~n

    Replace n with the number of commits you want to squash, and then follow the previous steps.

  • Interactive rebase for specific commits: Use git rebase -i to carefully pick and choose which commits to squash. This gives you fine-grained control over your commit history.

  • Squash history to one commit: For a clean slate, you can squash all commits in your branch into one, essentially condensing your branch's entire history. For more information on why the squash, rebase, merge strategy is better, see this article on why orgs ban merge commits.

  • Squash on merge: Platforms like GitHub offer the ability to squash commits when merging a pull request, providing a simpler alternative to manual squashing for some workflows.

Squashing is a part of the broader conversation around rebasing, and it’s importance in the modern developer’s workflow. For further reading, see the difference between squash and merge, or the importance of keeping pull requests small and focused.

For further reading on the git rebase -i command, see the official git documentation.

Stay unblocked. Ship faster.
Experience the new developer workflow - create, review, and merge code continuously. Get started with one command.
Learn more

Give your PR workflow
an upgrade today

Stack easier | Ship smaller | Review quicker

Or install our CLI.
Product Screenshot 1
Product Screenshot 2