How do you squash several messy commits into one before opening a pull request?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
Use git rebase -i HEAD~N (or rebase onto main) and mark the commits to fold with squash (keeps their message) or fixup (drops it). Git replays them into a single commit; edit the final combined message. Result: one clean commit per logical change, readable history for reviewers.
Detailed explanation
Interactive rebase opens an editor listing commits oldest-first with the pick command. Change pick to squash (or s) on commits to merge into the preceding one — their changes are combined and their messages concatenated for you to edit. Use fixup (or f) when you want the change but not the message (typo fixes, nits). Other actions: reword to edit a message without changing code, edit to pause and amend, drop to remove entirely. After saving, Git replays and stops if conflicts arise — resolve and rebase --continue. Common entry point: git rebase -i origin/main to squash everything ahead of main at once. Pair with --autosquash: mark fixups at commit time (git commit --fixup <sha>) and run rebase -i --autosquash to auto-order them. Squash before merging so main history stays linear and each commit is self-contained.
Example
# Squash last 4 commits into one:
git rebase -i HEAD~4
# editor: pick first, fixup the rest
# Mark fixups as you go, then auto-squash:
git commit --fixup=abc1234
git rebase -i --autosquash origin/mainInterview tip
Walk through the squash and fixup distinction with a concrete scenario (WIP commits, typo fixes), then mention --autosquash — it signals advanced daily usage.
Common mistakes
- Squashing commits that have already been pushed to a shared branch.
- Confusing squash (keeps messages) with fixup (drops them).
- Forgetting to rebase onto the latest main and shipping a conflict.