Git Rebase to Squash Commits to Most Recent MessagePublished on:
You’ve been working on a development branch over a couple days, testing things out and exploring solutions. You aren’t comfortable losing work, so you create superficial commits. They’re only for you so that you can recover prior work or failed experiments. Finally you arrive at a suitable solution and painstakingly create a commit with a message that will make you the talk of the town. Maybe the message includes benchmarks and well fleshed out reasoning for the chosen solution.
But something is wrong. The commits with superficial messages are still present. If you’re well prepared, you’ll be able to squash the commits together and copy and paste the golden message. However, sometimes that’s not possible.
So how do you squash several commits into one and take the most recent commit message?
- Checkout a temporary branch that is based off your dev branch
- Rebase it interactively against the desired base branch (typically main / master).
- Mark the first commit to be edited
- Mark the remaining commits to be fixed up
- When editing the commit, commit with the message from the dev branch (can either use the commit’s SHA or the branch’s name)
- You’re done and can rename this temporary branch as desired.
There is a stackoverflow thread that can be helpful as it contains some more information, but the solutions present are either sub-optimal for this scenario or not application. It is interesting to see how few people must have this question based on only a few upvotes. However, soon after devising this solution my co-worker asked me this exact question, so it must not be too rare.
For a follow along example, we first set up the git history to exhibit the undesired situation.
git init git commit --allow-empty -m "init" git checkout -b dev touch hello git add -A git commit -m "..." touch world git add -A git commit -m "..." touch foo git add -A git commit -m "the commit with good message"
Now we switch to our temporary branch
git checkout -b dev2 git rebase -i master
In the interactive screen, we’ll change the entries to edit the first one and fixup the rest:
edit b8847bc ... fixup 8d20a62 ... fixup 9e39d5b the commit with good message
Then we get dropped into the commit edit state and we will commit it with the good commit message with:
git commit --amend --reuse-message dev git rebase --continue
With the rebase done we should be in the desired state except for the temporary branch name, which can be fixed with a rename:
git branch -M dev
I don’t normally post quick little tutorials but since I probably wasted a half hour looking for a better solution I figured I’d write this down for my future self.
If you'd like to leave a comment, please email firstname.lastname@example.org