glossary

Squash Commits

The git operation of combining multiple commits into a single commit, typically used to clean up work-in-progress history before merging a feature branch.

Squashing collapses a series of commits into one, replacing their individual messages with a single combined message. It is performed via git rebase -i (interactive rebase) by marking commits as "squash" or "fixup", or automatically during a pull request merge with the "Squash and merge" option in GitHub and GitLab. Squashing is often used to clean up noisy WIP history (commits like "fix typo", "try again", "actually fix it") before the commits become part of the permanent main branch history. The resulting single commit is easier to revert if the feature needs to be removed. The tension between squashing and atomic commits is important to understand. Squashing multiple atomic commits into one loses the granularity that makes atomic commits valuable for bisecting and blame. A balanced approach is to maintain atomic commits during development and review, then squash only WIP noise before merge — preserving logical units while eliminating checkpoint clutter.

# Before squash: 5 WIP commits on feature branch
wip: start login flow
fix: forgot to import component
fix: handle edge case
# After squash merge: one clean commit on main
feat(auth): add OAuth2 login flow with PKCE

git-agent creates clean, atomic commits from the start, reducing the need to squash. When you use git-agent commit, each logical change is already committed separately with a meaningful message, so the history is ready for review and merge without cleanup.

brew install gitagenthq/tap/git-agent
Should I squash commits before merging a pull request?
It depends on commit quality. If each commit in the PR is already a clean atomic commit with a conventional message (as git-agent produces), preserving them individually gives better history. Squash WIP checkpoints, not meaningful atomic commits.
Does squashing break git bisect?
Squashing reduces bisect granularity. If ten atomic commits are squashed into one, bisect can only identify that one commit as the source of a regression — not which of the ten original changes introduced it.
Is 'Squash and merge' in GitHub the same as git rebase squash?
They produce the same result (one commit) but differ in how the commit is created. GitHub's squash merge creates a new merge commit with all changes; interactive rebase squash modifies the local branch history before merge.