DEV Community

Cover image for How to Squash Like a Grand‑master
Emrah G.
Emrah G.

Posted on

How to Squash Like a Grand‑master

Ship one clean commit & keep your history zen‑like, even on long‑running feature branches.


Why squash at all?

  • 🚢 Atomic history → Every merge commit is a single, focused unit of work.
  • 🕵️‍♀️ Easy bisect → Narrow regressions in seconds.
  • 🧩 No ‑fix, ‑rework, ‑typo commits → Reviewers see only what matters.
  • 📜 Readable release notes → Git log ≈ changelog.

If your team pushes “work‑in‑progress” to keep CI green or share progress, history easily becomes a Gordian knot. The technique below slices through it—without risky rebase marathons.


The “Temp‑Squash” pattern

We’ll squash develop into one commit while keeping the branch name & PR intact. Change develop with your original branch name and master with your target branch in the following script. You can run them one by one in the terminal.

# 1 – Create a throw‑away branch off the latest master
$ git checkout -b develop-temp master

# 2 – Squash‑merge your feature into it
$ git merge --squash develop
$ git commit # write a perfect message

# 3 – Teleport the clean commit back onto the original branch
$ git checkout develop
$ git reset --hard develop-temp   # pointer moves, history replaced

# 4 – House‑keeping
$ git branch -d develop-temp      # delete temp branch
$ git push -f origin develop  # force‑push once
Enter fullscreen mode Exit fullscreen mode

Result:

  • One shiny commit on your branch.
  • CI & open pull‑request auto‑update (GitHub/GitLab).
  • No risk of rebase conflicts across dozens of local clones—only you rewrote.

Step‑by‑step explained

1 — branch off current master

A temp branch guarantees we squash on top of the latest mainline. Any new fixes on master are included without touching your teammates’ work.

2 — git merge --squash

  • Combines all commits from the feature branch into the index.
  • Nothing is recorded yet—no merge commit.
  • git commit turns the staged changes into one commit.

💡 Tip: use conventional‑commits (feat:/fix:) + issue key so release notes write themselves.

3 — git reset --hard <temp>

Moves the branch pointer to your fresh commit. No reapply, no rebase, no conflict.

4 — git push -f origin develop

Force‑push once

Happy squashing!

cover_image: https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dthrvwk4d5yzakoonkt.png

Top comments (0)