Next.js starter your AI actually understands. Ship internal tools in days not weeks. Pre-order $199 $499 → [Get it now]

How to squash commits in Git

Squashing commits combines multiple small commits into a single, meaningful commit before merging a feature branch, making the project history clean and easy to navigate. As the creator of CoreUI with 25 years of open-source development experience, I review pull requests daily and always ask contributors to squash work-in-progress commits before merging. The most straightforward method is interactive rebase with git rebase -i, which gives you full control over which commits to squash and what message to use. Clean commit history makes git log, git bisect, and git blame significantly more useful.

Use interactive rebase to squash the last N commits into one.

# Squash the last 3 commits into one
git rebase -i HEAD~3

This opens an editor showing the last 3 commits:

pick a1b2c3d First commit message
pick e4f5a6b Second commit message
pick 7c8d9e0 Third commit message

Change pick to squash (or s) for the commits you want to combine:

pick a1b2c3d First commit message
squash e4f5a6b Second commit message
squash 7c8d9e0 Third commit message

Save and close the editor. Git opens a second editor to write the combined commit message. Write a clean, descriptive message and save.

The pick command keeps the commit as-is. squash folds the commit into the one above it. Only the top commit uses pick — all others become squash.

Squashing All Commits Since Branching from Main

Squash all commits on your feature branch in one step.

# Find the commit where your branch diverged from main
git merge-base HEAD main

# Rebase interactively from that commit
git rebase -i $(git merge-base HEAD main)

git merge-base HEAD main returns the SHA of the common ancestor commit. Passing it to git rebase -i opens the editor with all commits made since branching, no matter how many there are.

Squash Using –squash When Merging

Squash all branch commits into one when merging.

# Switch to main branch
git checkout main

# Squash all commits from feature branch into one staged change
git merge --squash feature/my-feature

# Commit the squashed change
git commit -m "feat: add my feature"

git merge --squash applies all the changes from the feature branch as a single staged commit without creating a merge commit. You then write the final commit message. The feature branch remains unchanged — you can delete it after merging.

Pushing After Squashing

Squashing rewrites history, so you need to force push.

# Push the squashed commits to the remote
git push origin feature/my-feature --force-with-lease

--force-with-lease is safer than --force — it fails if someone else has pushed to the same branch since your last fetch. Always use --force-with-lease instead of --force when rewriting history on shared branches.

Best Practice Note

This is the same squash workflow used for all CoreUI pull requests — feature branches are squashed before merging so the main branch history contains one commit per feature. Avoid squashing on main or master directly; only squash on feature branches before they’re merged. If you need to clean the Git history more extensively, interactive rebase supports reword, edit, drop, and fixup commands for full control over every commit.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author