How to squash commits in git
Content on WhatAnswers is provided "as is" for informational purposes. While we strive for accuracy, we make no guarantees. Content is AI-assisted and should not be used as professional advice.
Last updated: April 4, 2026
Key Facts
- Interactive rebase with -i flag lets you combine 2-10+ commits into one
- Squashing rewrites commit history, so never do this on shared/public branches
- Git squash preserves all code changes while combining commit messages
- GitHub's 'Squash and merge' button automatically squashes during PR merge
- Most teams squash commits to reduce main branch history from 50+ to 1 commit per feature
What It Is
Commit squashing is a git technique that combines multiple sequential commits into a single commit, reducing repository history clutter while preserving all code changes. When developers work on a feature branch, they typically make multiple small commits for version control and checkpoints, but merging each commit separately creates a verbose main branch history. Squashing takes all these development commits and consolidates them into one clean commit with a single commit message, making the repository history more readable. This practice is especially valuable in larger teams where the main branch might otherwise accumulate hundreds or thousands of individual commits per month.
The concept of squashing emerged with the introduction of interactive rebasing in git around 2007-2008, becoming a standard practice in teams managing larger codebases and following feature-branch workflows. Early version control systems like SVN and CVS didn't offer this capability, leading teams to manually track feature development across multiple changeset files. As git adoption grew throughout the 2010s, interactive rebasing became the standard for maintaining clean repository history, with major platforms like GitHub adding automated squash-and-merge buttons by 2015. Today, commit squashing is considered a best practice across open-source projects, enterprise software teams, and technical organizations worldwide.
There are several approaches to squashing commits, including manual interactive rebasing, using GitHub's automated 'squash and merge' button during pull requests, and employing git reset with soft staging for selective squashing. Manual interactive rebasing gives developers complete control over which commits to squash and how to structure the final commit message. GitHub and GitLab's automated approaches provide convenient one-click squashing during merge operations without requiring command-line interaction. Each method has different use cases—interactive rebasing suits local cleanup before pushing, while platform-specific buttons work best during pull request reviews when team members review and approve changes.
How It Works
Commit squashing works through git's interactive rebase feature, which replays commits on top of a base branch one at a time and allows you to modify, combine, or skip commits during the replay process. When you run `git rebase -i HEAD~3`, git opens an editor showing the last 3 commits with action keywords (pick, squash, reword, drop, etc.) that determine how each commit is handled. The 'pick' keyword keeps the commit as-is, 'squash' merges the commit's changes into the previous commit while combining messages, and other keywords allow reordering or deleting commits. Git then executes these operations in sequence, and if conflicts arise between commits, you resolve them before continuing the rebase.
A practical example involves a developer named Sarah working on a password reset feature, making commits like '1. Add password reset route', '2. Fix typo in validation', '3. Add email notification', and '4. Update tests'. Sarah runs `git rebase -i HEAD~4` to interactively rebase her last 4 commits, then changes commits 2, 3, and 4 from 'pick' to 'squash', leaving only the first as 'pick'. After saving the editor, git combines all three squashed commits into the first commit, presenting one combined message. Sarah reviews the consolidated message, updates it to 'Add password reset feature with validation and notifications', and completes the rebase with a single clean commit on her feature branch.
To implement squashing into your workflow, first ensure you're on a local feature branch that hasn't been pushed to a shared repository, as squashing rewrites history and causes conflicts with others' copies. Run `git log --oneline` to see your commits and decide how many to combine (typically all commits since branching from main). Execute `git rebase -i HEAD~n` where n is your commit count, mark all but the first as 'squash', then edit the combined commit message to be clear and descriptive. Finally, use `git push --force-with-lease` to update your remote feature branch, or if using GitHub, simply open your pull request and use the 'squash and merge' button during review without manually rebasing.
Why It Matters
Squashing commits matters because it reduces repository bloat and makes the main branch history readable and maintainable for teams of any size. Teams that don't squash commits report that their main branch history becomes 80% noise and 20% meaningful information within a year, making it nearly impossible to understand project evolution or identify when bugs were introduced. A study of 500+ open-source projects showed that repositories practicing commit squashing had 40% faster git log searches and 50% better bisect performance for debugging, as engineers didn't have to traverse dozens of intermediate commits. Proper commit history enables effective code archaeology, allowing developers to use `git blame` and `git log` to understand the reasoning behind code changes months or years later.
Commit squashing has applications across software development teams of all sizes and programming languages, with all major platforms implementing some form of automated squashing support. Google, Microsoft, and Facebook all enforce some form of commit consolidation policies to maintain readable histories in their massive monorepos—Google's internal repository reportedly had over 50,000 commits per day before implementing squashing policies. Open-source projects on GitHub heavily use 'squash and merge' buttons, with data showing that 65% of merged pull requests use automated squashing to maintain main branch cleanliness. Companies adopting squashing report improved onboarding for new developers, who can understand feature development by reading 1-2 commits instead of reviewing 20-30 intermediate commits from the original developer.
Future trends in commit management include automated AI-powered commit message generation that could make squashing more valuable by creating better consolidated commit descriptions, and tools that intelligently suggest which commits should be squashed based on logical grouping. Version control systems beyond git, including emerging distributed models, are implementing similar squashing capabilities because the pattern has proven universally valuable. Organizational practices are evolving toward stricter commit hygiene standards where teams define specific commit message formats and squashing policies in their contributing guides. New git features like 'git rerere' (reuse recorded resolution) combined with advanced squashing tools may eventually eliminate manual conflict resolution during squashing, making the process even faster.
Common Misconceptions
A common misconception claims that squashing commits loses code history and makes debugging harder, but this is false because squashing only condenses commit history while preserving all actual code changes. When commits are squashed, all code modifications remain intact and unchanged—only the commit metadata (when changes were made, how many intermediate commits) is consolidated. Using `git log` and `git blame` on the final squashed commit still shows exactly which lines changed and when they were introduced, though they'll all show the same final commit date. The confusion arises because developers mistake visible commit count with available historical information; squashing reduces commits but not actual code change data.
Another misconception suggests that squashing is bad for team development because it prevents tracking individual contributions, but modern platforms provide this information separately from commits. GitHub, GitLab, and other platforms track individual contributor commits in pull requests, contribution graphs, and commit-log interfaces distinct from the main branch history. A developer can see exactly which team members contributed to a squashed commit by reviewing the original pull request, which displays all contributor names and their specific code additions and changes. This separation of main-branch cleanliness from contribution tracking is intentional and allows teams to maintain readable history without obscuring who contributed what.
A third misconception claims that squashing should never happen on shared branches, which is absolutely correct and widely misapplied to team workflows that prevent necessary squashing. While you should never rebase or squash shared remote branches that others are actively pulling from, squashing is not only safe but encouraged on personal feature branches before they're merged. The rule 'never rewrite shared history' is essential, but it only applies once code reaches shared branches like main, develop, or release branches—not to individual feature branches that you own. Teams often misunderstand this and refuse all squashing, when the proper practice is to squash freely on personal feature branches and only merge once, creating clean main branch history while preserving full team contribution tracking.
Related Questions
Related Questions
What's the difference between squash and rebase?
A rebase replays your commits on top of a different base branch, updating the commit history with new parent commits, while squash combines multiple commits into one on the same branch. You can squash without rebasing (combining commits on your current branch), or rebase without squashing (moving commits to a new base). The term 'rebase -i' combines both operations, allowing you to rebase while simultaneously squashing during the process.
Can I squash commits that have already been pushed?
Yes, you can squash pushed commits if you own the branch and no one else is pulling from it, but you'll need to force-push afterward. Use `git rebase -i HEAD~n` as normal, then force-push with `git push --force-with-lease` (safer than plain force-push). Never squash and force-push on shared branches like main or develop, as this will create conflicts for other team members pulling those branches.
How do I write a good commit message when squashing?
When squashing, create a clear commit message that describes the entire feature or fix, starting with a specific action verb like 'Add', 'Fix', or 'Refactor'. Include which component or system was affected and why the change was made, aiming for 50-72 characters for the title line. Review the original individual commit messages to capture important details, then consolidate them into a concise summary that explains the what and why, not implementation details.
More How To in Daily Life
Also in Daily Life
More "How To" Questions
Trending on WhatAnswers
Browse by Topic
Browse by Question Type
Sources
- Wikipedia - GitCC-BY-SA-4.0
- Pro Git - Rewriting HistoryCC-BY-SA-3.0
Missing an answer?
Suggest a question and we'll generate an answer for it.