{"post":{"slug":"how-to-squash-commits-2026","title":"How to squash commits in 2026","excerpt":"Squashing collapses multiple commits into one before merging, keeping the main branch history readable. Here are the three ways to do it and when each applies.","category":"code","date":"April 18, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">S</span>quashing commits is the practice of collapsing a sequence of work-in-progress commits — \"WIP\", \"fix typo\", \"oops forgot file\" — into a single meaningful commit before it lands on the main branch. A clean history is not about aesthetics; it makes `git bisect`, `git log`, and `git revert` dramatically faster to use.\n\n## What changed in 2026\n\n- **GitHub's \"Squash and merge\" is the default merge strategy for most teams** — it enforces one-commit-per-PR automatically without any local git knowledge required.\n- **Conventional Commits** (`feat:`, `fix:`, `chore:`) are widely adopted; squashed commit messages are expected to follow the format for automated changelogs.\n- **`git rebase --autosquash`** is underused but powerful — prefix a commit message with `fixup!` or `squash!` and rebase picks it up automatically.\n- **Linear history is increasingly enforced** on main via branch protection rules — merge commits are blocked, so squash-and-merge or rebase-and-merge are the required strategies.\n\n## Method 1 — GitHub (or GitLab) squash-and-merge\n\nThe simplest path: no local git knowledge needed.\n\n1. Open your pull request.\n2. Click the dropdown arrow next to **Merge pull request**.\n3. Select **Squash and merge**.\n4. Edit the commit message (GitHub pre-fills it with all commit messages concatenated).\n5. Click **Confirm squash and merge**.\n\nThe result is a single commit on main. Your feature branch is unchanged. After merging, delete the branch.\n\n**When to use:** any PR where the branch commits are messy and you want a clean main-branch history.\n\n## Method 2 — interactive rebase\n\nFor squashing locally before pushing (or before a PR):\n\n```bash\n# Squash the last 4 commits\ngit rebase -i HEAD~4\n```\n\nGit opens your editor with a list:\n\n```\npick abc1234 Add user model\npick def5678 WIP auth\npick ghi9012 fix typo in migration\npick jkl3456 actually working auth\n\n# Commands:\n# p, pick   = use commit\n# r, reword = use commit, but edit the commit message\n# s, squash = use commit, melt into previous commit\n# f, fixup  = like squash, but discard this commit's message\n```\n\nChange `pick` to `squash` (or `s`) for commits you want to merge into the one above them:\n\n```\npick abc1234 Add user model\nsquash def5678 WIP auth\nfixup ghi9012 fix typo in migration\nsquash jkl3456 actually working auth\n```\n\nSave and close. Git opens a second editor for the final combined commit message. Write a clean, descriptive message, save, and you are done.\n\n```bash\n# Then force-push your branch (only if it was already pushed)\ngit push --force-with-lease\n```\n\n## Method 3 — git merge --squash\n\nMerges a branch into the current branch as a single staged change, which you then commit manually:\n\n```bash\ngit checkout main\ngit merge --squash feature/my-feature\ngit status          # all changes from the branch are now staged\ngit commit -m \"feat: add user authentication (#42)\"\n```\n\nThis gives you full control over the commit message. It does not create a merge commit. The feature branch still exists and still has its individual commits.\n\n**When to use:** when you want to write the commit message from scratch and the feature branch is yours alone.\n\n## Squash + autosquash workflow\n\nPre-mark commits for squashing while you work:\n\n```bash\n# Create a fixup commit for an earlier commit\ngit commit --fixup abc1234\n\n# Later, let rebase pick them all up automatically\ngit rebase -i --autosquash HEAD~5\n```\n\n`--autosquash` reorders commits prefixed with `fixup!` or `squash!` and sets their action automatically — you just review and save.\n\n## What the final commit message should look like\n\nFollowing Conventional Commits:\n\n```\nfeat(auth): add JWT-based user authentication\n\n- Introduces /login and /logout endpoints\n- Signs tokens with RS256; public key in env\n- Adds middleware to validate Bearer tokens on protected routes\n\nCloses #42\n```\n\nOne subject line, an optional blank line, then a body if the change needs explanation. GitHub's squash dialog pre-fills from all commit messages — clean it up before confirming.\n\n## Squash workflow comparison\n\n| Method | Where | Rewrites branch history? | Needs local git? |\n| --- | --- | --- | --- |\n| GitHub squash-and-merge | Remote | No (branch unchanged) | No |\n| git rebase -i | Local | Yes | Yes |\n| git merge --squash | Local | No (branch unchanged) | Yes |\n| --autosquash | Local | Yes | Yes |\n\n## How to pick\n\n1. **Merging a PR with messy WIP commits?** → Use GitHub/GitLab squash-and-merge.\n2. **Want to clean up before requesting review?** → `git rebase -i HEAD~N`.\n3. **Integrating a long-lived branch into another branch locally?** → `git merge --squash`.\n4. **Regularly creating fixup commits as you work?** → Set up `--autosquash` with `git config --global rebase.autoSquash true`.\n\n## Common mistakes\n\n**Squashing after a colleague has checked out your branch.** Their local branch diverges from yours after the force-push. Communicate before rewriting history on a shared branch.\n\n**Forgetting `--force-with-lease` after a rebase.** A plain `git push` is rejected; `--force` is dangerous; `--force-with-lease` is the safe option.\n\n**Writing \"squash\" in the final commit message.** The message that lands on main should describe the feature, not the git operation. Delete all the \"WIP\" and \"fix typo\" lines from the squash editor.\n\n**Squashing a commit that is already on main.** You are rewriting shared history. This will cause divergence for everyone who has pulled main.\n\n## What to skip\n\n- **Squashing every commit including meaningful atomic steps** — some teams keep one commit per logical change (refactor, feature, test) rather than one commit per PR. Know your team's convention.\n- **Interactive rebase on main** — only rebase feature branches.\n- **`git push --force` (without --lease)** after rebasing — use `--force-with-lease` always.\n\n## FAQ\n\n**Does squashing lose commit metadata like author and date?**\nBy default, the squashed commit uses your author info and the current timestamp. Individual authors from squashed commits appear in the squash message body on GitHub but not in the git object.\n\n**Is squash-and-merge or rebase-and-merge better for main?**\nSquash-and-merge gives you one commit per PR — easiest to revert, easiest to read. Rebase-and-merge preserves individual commits but requires they all be clean. Pick one and enforce it consistently via branch protection settings.\n\n**How do I squash commits on a branch that has already been merged?**\nYou cannot cleanly — the history is shared. Use `git revert` on main to undo the feature, then rewrite and re-merge. Easier to squash before merging.\n\n**What is `git commit --fixup` and when should I use it?**\nIt creates a commit with the message `fixup! <original message>`, signaling to `git rebase --autosquash` that it should be folded into the original. Use it while developing to mark \"this fixes a mistake in commit X\" without interrupting your flow.\n\n## Where to go next\n\n- [How to undo a git commit in 2026](/blog/how-to-undo-a-git-commit-2026)\n- [How to fix a merge conflict in 2026](/blog/how-to-fix-a-merge-conflict-2026)\n- [How to write a README in 2026](/blog/how-to-write-a-readme-2026)","hue":322,"metaTitle":"How to Squash Commits in 2026","metaDescription":"Three ways to squash git commits in 2026: interactive rebase, GitHub squash-and-merge, and git merge --squash. When to use each and common pitfalls.","keywords":["how to squash commits 2026","git squash commits","git rebase interactive squash","github squash and merge","git merge squash","git rebase -i fixup","squash commits before merge","git clean history","combine git commits","git squash workflow 2026"],"tldr":["**Squash-and-merge on GitHub is the easiest path** — one click collapses all PR commits into a single commit on main without touching your local branch.","**Interactive rebase gives full control** — rebase -i lets you reorder, edit, fixup, or squash any subset of commits before the PR is merged.","**git merge --squash for manual squash merges** — merges a branch as a single staged commit that you then commit yourself.","**Squash before force-pushing, not after** — rewriting history after teammates have checked out your branch creates divergence.","**Skip:** squashing every commit on main retroactively — it rewrites shared history and breaks everyone working from those SHAs."],"readTime":"5 min read","wordCount":1147},"related":[{"slug":"git-squash-vs-rebase-2026","title":"Git Squash vs Rebase in 2026: What Each One Does","excerpt":"Squashing collapses commits into one; rebasing replays commits onto a new base. Here is what each git command actually does, and when to reach for which one.","category":"code","date":"July 2, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":280},{"slug":"git-rebase-vs-merge-2026","title":"Git rebase vs merge in 2026: which strategy keeps your history clean","excerpt":"The rebase vs merge debate has a clear answer once you understand what each command actually does to your commit graph and when each one creates problems.","category":"code","date":"April 13, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":313},{"slug":"git-workflow-best-practices-2026","title":"Git workflow best practices in 2026: keep history clean and shipping","excerpt":"A practical guide to Git workflows in 2026 - branching, commits, pull requests, and the habits that keep history readable and your team unblocked.","category":"code","date":"May 10, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":240}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"how-to-split-bills-with-roommates-2026","title":"How to split bills with roommates in 2026: fair systems and the right apps","excerpt":"Bill splitting is one of the top causes of roommate conflict. Here is how to set up a fair, transparent, and low-friction system that actually holds together in 2026.","category":"finance","date":"April 18, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":286},"older":{"slug":"how-to-start-composting-2026","title":"How to start composting in 2026: the no-nonsense beginner guide","excerpt":"Composting is simpler than most guides make it. Here is a 2026 setup for beginners — what to compost, what to avoid, and how to get usable compost fast.","category":"guides","date":"April 18, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":140}}