Blog Squash commits without breaking your branch

Squash commits without breaking your branch

2 min read

Squash commits without breaking your branch
TL;DR Use interactive rebase to squash a run of scrappy commits into a few meaningful ones before you open a pull request. Rebase only local, unpushed commits, keep a backup branch, and you can tidy history safely and undo it if needed.

You finish a feature and your branch has a dozen commits like "wip", "fix typo", and "actually fix it". Functionally fine, but a reviewer should not have to wade through that. Squashing tidies it into a clean, readable history before the pull request. Done right, it is safe and reversible.

Make a safety net first

Before rewriting anything, branch off so you have a way back:

git branch backup-before-squash

If the squash goes wrong, that branch still points at your original commits.

Squash with interactive rebase

Rebase the last few commits interactively:

git rebase -i HEAD~6

Git opens an editor listing the commits, oldest first:

pick a1b2c3 add the feature
pick d4e5f6 wip
pick 7g8h9i fix typo

Change pick to squash (or s) on the commits you want folded into the one above:

pick a1b2c3 add the feature
squash d4e5f6 wip
squash 7g8h9i fix typo

Save, and git combines them, then lets you write one clean commit message for the result.

The one rule: only local commits

Squash commits that live only on your machine. Once you have pushed and others may have built on them, rewriting that history causes pain for everyone downstream. If your branch is already shared, either leave it, or coordinate with the team before rewriting.

If it goes wrong

You have two ways back. Reset to the backup branch you made:

git reset --hard backup-before-squash

Or find the pre-squash state in the reflog and reset to it:

git reflog        # locate the commit before the rebase
git reset --hard <hash>

Why bother

A clean history is a gift to whoever reviews your code and to whoever reads the log a year from now, including you. A single commit that says what changed beats a dozen that record how you flailed toward it. Squash the noise, keep the signal, and with a backup branch and reflog behind you, you can do it without ever risking the work.

FAQ

What does squashing commits do?

It combines several commits into one, so a messy trail of work-in-progress commits becomes a single clean commit with a proper message. It makes the history easier to read and review without changing the final code.

Is squashing safe?

It is safe on local, unpushed commits, which is where you should do it. Squashing commits you have already shared rewrites history others may depend on, so avoid that on shared branches unless the team agrees.

How do I undo a bad squash?

Two safety nets: make a backup branch before you start, so you can return to it, and remember that git reflog records where your branch was, so you can reset back to the pre-squash state if something goes wrong.