How to Squash Commits in Git (Step-by-Step with 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.
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 freeGit 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 buttond4e5f6 Fix login button stylingg7h8i9 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 buttonpick d4e5f6 Fix login button stylingpick 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 isreword
: Change the commit messageedit
: Amend the commitsquash
: Combine with previous commitdrop
: 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 buttonsquash d4e5f6 Fix login button stylingsquash 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 stylingRename 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 IDSuccessfully 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 HEADAutomatic 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
ordevelop
- 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.
'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 teamRelated articles
- Article
How to Use Git Rebase: A Complete Guide
Learn `git rebase` to clean up commit history. Complete guide covering what is `git rebase`, merge vs rebase, and best practices. - Article
How to Revert to Previous Commits Using Git Reset and Revert
Learn how to roll back to previous commits in Git using git reset and git revert commands. Step-by-step guide to undo changes and manage your commit history effectively. - Article
Handy Git Operations
Git provides us with a vast number of different commands that are listed on the documentation which can be intimidating at first. We will break down a couple that are powerful for daily tasks.
Learn more on Codecademy
- Free 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.Beginner Friendly1 hour - Free course
Using Git for DevOps: Using Git Effectively
Become proficient in Git for DevOps, including repository management, Git commands, GUI, distributed workflows, branching, Git server protocols, and Gitflow.Intermediate1 hour - Free course
Learn Git: Branching and Collaboration
Learn how to create, merge, clone, and fetch Git branches to collaborate with other developers.Beginner Friendly1 hour