Squash
About
In Git, squashing means combining multiple commits into one single commit.
It is most commonly used during:
Interactive rebase (
git rebase -i
)Merge with squash (
git merge --squash
)
Squashing does not change our code, it changes our commit history.
The primary goal is to simplify the commit history by removing unnecessary commit boundaries (e.g., WIP, typo fixes, partial steps) and creating a single cohesive commit that represents a logical unit of work.
Why Squash Exists ?
In collaborative development, it’s common to work in small, iterative steps:
We might have 10 small commits that represent fixing typos, renaming variables, adjusting logic, or debugging.
While useful during development, these small commits:
Pollute history.
Make reviewing difficult.
Add noise to blame/log commands.
Squashing exists to clean this up. It rewrites those granular steps as if the work had been done in a single, clean, well-thought-out commit.
It is especially useful before merging a feature branch into a long-lived branch like main
.
How Squashing Works ?
There are two major ways to squash commits:
1. Using git rebase -i
git rebase -i
This allows fine-grained control.
We will see:
Change to:
Git will:
Replay the first commit as-is.
Combine the next two into the first.
Prompt us to write a combined commit message.
2. Using git merge --squash
git merge --squash
This squashes commits across branches, not within a branch.
What happens:
Git collects all changes introduced by
feature-branch
.Prepares them for a single commit.
We write the commit message manually.
No merge commit is created, and the history of
feature-branch
is not preserved.
Example
Initial Scenario
We are working on a feature
branch that branched off from main
at commit C
.
Commits
D
,E
, andF
are all part of our in-progress work.Let’s say:
D
: Added new service class.E
: Fixed method name.F
: Added tests and finalized logic.
These 3 commits are small and related to a single feature.
Goal: Squash D
, E
, F
into a single commit on feature
.
D
, E
, F
into a single commit on feature
.We run:
In the editor:
Change it to:
Git combines E
and F
into D
. We are prompted to write a new commit message — something like:
Implement new service with final logic and tests
Now our commit history looks like this:
Where G
is the new squashed commit combining D+E+F
.
What Actually Happened Internally ?
Commits
D
,E
, andF
were rewritten into a single new commitG
.G
has a new commit ID.Original commits are no longer in the history of the branch.
No changes to file content unless conflicts were resolved differently.
The rebase rewrote history starting from
C
.
When to Use Squash and When Not ?
Use Squash When
Do Not Use Squash When
We want to keep commit history clean and minimal
We need to preserve the full development history for traceability
We are preparing a feature branch for merging into main
The branch is shared with others — squashing will rewrite shared history
The intermediate commits are messy (e.g., “fix typo”, “debugging step”, etc.)
Each commit contains meaningful, standalone changes we may want to track later
We are submitting a pull/merge request and want one logical commit
Our team wants to review changes step-by-step as we made them
We want a single revert point in case the feature needs to be rolled back
The work is exploratory and we want to preserve all steps for learning/debug
Our team enforces a one-feature-one-commit policy
The repository uses a linear, detailed commit history policy
We are cleaning up WIP commits before pushing
We already pushed the commits and others are basing work on them
We want to rebase and integrate changes cleanly without polluting main history
We need to retain authorship of individual commits (in case of multiple devs)
Last updated
Was this helpful?