Articles

How to Squash Commits in Git (Step-by-Step with Examples)

Learn how to squash commits in Git with this step-by-step guide. Master Git squash using interactive rebase and `git merge --squash` with practical examples.

What is Git squash?

Git squash is the process of combining multiple Git commits into a single commit. This is typically done during an interactive rebase or by using the git merge --squash command.

Using Git squash helps us:

  • Maintain a clean, linear Git history
  • Make code reviews simpler by showing a single logical change
  • Reduce noise caused by experimental or fix-up commits
  • Improve collaboration by preventing commit bloat in shared branches

By squashing commits, we make our repositories more maintainable, which is crucial in long-term projects.

Now that we know what Git squash is, let’s learn how to do it using interactive rebase.

Related Course

Learn Git: Introduction

Learn how to track changes in your code and switch between different versions with Git, an open-source version control system.Try it for free

Git squash using interactive rebase

The most common and flexible way to squash commits in Git is by using an interactive rebase. This method gives us full control over how commits are combined, reordered, or modified before integrating them into a cleaner history.

Let’s walk through a real-world example, step-by-step.

Imagine we’ve made three commits on a feature branch while developing a new feature. These commits might look like:

a1b2c3 Add login button
d4e5f6 Fix login button styling
g7h8i9 Rename login button ID

These changes are related, but splitting them into three separate commits might be unnecessary for the main branch. So, we want to squash these commits into one (the topmost commit).

To do so, run this command in the terminal:

git rebase -i HEAD~3

In this command:

  • git rebase -i: Starts an interactive rebase.
  • HEAD~3: Specifies the most recent 3 commits to be rebased.

Upon running the command, the default text editor on the machine will be launched with this content:

pick a1b2c3 Add login button
pick d4e5f6 Fix login button styling
pick g7h8i9 Rename login button ID

Here, pick is an action that we can perform on a particular commit. Let’s check out what this action does, along with some other ones:

  • pick: Use commit as is
  • reword: Change the commit message
  • edit: Amend the commit
  • squash: Combine with previous commit
  • drop: Remove the commit

Since we want to squash the second and third commits into the first commit, we need to change pick to squash for these commits:

pick a1b2c3 Add login button
squash d4e5f6 Fix login button styling
squash g7h8i9 Rename login button ID

After saving the file, Git will prompt us to create a combined commit message. We’ll see something like:

# This is a combination of 3 commits.
# The first commit’s message is:
Add login button
# The commit messages from the other commits:
Fix login button styling
Rename login button ID

We can clean this up to something concise:

Add login button with proper styling and updated ID

Then, save and exit the editor.

If everything goes well, Git will show a success message like:

[detached HEAD 1a2b3c4] Add login button with proper styling and updated ID
Successfully rebased and updated refs/heads/feature-branch.

Next, let’s look at a simpler alternative: git merge --squash.

Git squash using git merge --squash

While interactive rebase gives us full control over commit history, there’s a simpler alternative: using the git merge --squash command. This approach is ideal when we want to incorporate a feature branch into the main branch and flatten all the commits into a single one—without preserving the original commit history from the feature branch.

This method is especially helpful when:

  • We want a clean, one-commit summary of all changes from a feature branch
  • We don’t need to preserve granular commit details from the original branch
  • We prefer not to deal with rebase conflicts or editing commit messages manually

Let’s say we’ve been working on a feature branch named feature/login-form, and it contains multiple commits. Here’s how we can squash those commits into one when merging into the main branch:

Step 1: Check out the target branch

First, switch to the branch where you want to apply the squashed changes (usually the main or develop branch):

git checkout main

Step 2: Run the git merge --squash command

Now, use the git merge --squash command to pull in all changes from the feature branch — but without actually merging the commit history:

git merge --squash feature/login-form

Git applies all the changes from feature/login-form as if they were made in your current branch, but hasn’t created a merge commit yet.

We’ll see an output like:

Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested

This means Git has staged all the changes but left the commit action for us to finalize.

Step 3: Commit the squashed changes

Now that all the changes are staged, create a single commit to represent them:

git commit -m "Add login form with validation and styling"

This single commit will contain all the changes from the feature branch, squashed together into a tidy summary.

With the methods covered, let’s discover the scenarios where it is ideal to perform Git squash.

When to squash Git commits

We should consider squashing Git commits in these scenarios:

  • Before merging a feature branch into main or develop
  • When we have multiple “work-in-progress”, or “fix typo” commits.
  • During pull request reviews where reviewers request a cleaner commit history
  • When contributing to open-source projects that require one commit per feature/fix

Understanding the right moment to squash commits brings us to the next question—why should we squash them at all?

Why squash Git commits?

There are several reasons for squashing commits in Git:

  • Increase clarity by summarizing changes in a single commit
  • Reduce potential merge conflicts
  • Make rollbacks and cherry-picks easier and more effective

Squashing is especially useful in teams and open-source communities where squashing commits can signal a well-thought-out, complete change.

Now that we know the “why”, let’s go through some best practices for squashing commits in Git.

Best practices for squashing commits in Git

To make the most out of squashing commits in Git, we can follow these best practices:

  • Use squash before merging to the main branch
  • Avoid squashing after shared work has already been pushed unless all collaborators agree
  • Write clear and descriptive commit messages after squashing
  • Automate squash policies using tools like GitHub’s “Squash and Merge” option

These best practices ensure a clean project history without disrupting the team’s workflow.

Conclusion

In this guide, we learned about Git squash and its importance in development workflows. We explored two primary methods: using git rebase -i for interactive squashing and git merge --squash for flattening changes during a merge. We also discussed when and why to squash commits and shared best practices to maintain a clean and understandable Git history.

Squashing commits isn’t just about tidiness—it’s about communication. Each commit tells a story, and when that story is well-written, everyone on the team benefits. By learning how to squash commits in Git, we make our projects easier to understand and maintain.

If you want to expand your knowledge of Git, check out the Learn Git & GitHub course on Codecademy.

Frequently asked questions

1. Is squashing commits a good idea?

Yes. Squashing commits is generally recommended for cleaning up a messy commit history before merging to the main branch. It improves readability and simplifies collaboration.

2. When to merge vs rebase?

  • Use rebase when integrating changes linearly without creating merge commits.
  • Use squash during rebase to combine multiple commits.

3. What is the difference between squash and merge commit?

  • Squash commit: Combines all commits into one
  • Merge commit: Preserves the full commit history and creates a new commit to join branches.

4. What is the difference between Git stash and squash?

  • Git stash: Temporarily saves changes without committing them.
  • Git squash: Permanently combines multiple commits into one.

5. Are squashed commits lost?

Technically, yes—original commits are rewritten. However, Git keeps backups in reflog (temporarily), and you can recover them if needed, unless the branch is deleted.

Codecademy Team

'The Codecademy Team, composed of experienced educators and tech experts, is dedicated to making tech skills accessible to all. We empower learners worldwide with expert-reviewed content that develops and enhances the technical skills needed to advance and succeed in their careers.'

Meet the full team