- Published on
#TIL: Using git rebase to combine commits
I normally use
git rebase with
--fixup commits, and haven't had a need [until now] to take a bunch of commits made at different times and combine them.
Where possible, I prefer commits on the
main branch to represent some "unit" of work1, to prevent a bunch of commits where you might be going back and forth on something from cluttering up the history2.
The PRs3 I submit day-to-day are normally isolated features that make this easy to accomplish. I use
rebase a lot within a branch for myself before submitting a PR, but the extent is normally:
$ git add -p # add the specific thing I want to revise $ git commit --fixup <hash> # mark this as a fixup $ git rebase -i --autosquash <hash>~1 # go to 1 commit _before_ the commit to be fixed
However, in building this blog there's been a few times where I added bits of things at different times, 20+ commits apart, and (for whatever reason4) didn't realize I wanted them all combined at the time of committing.
Specifically, I wanted to combine some commits to know "here's everything I did to get
<specific feature> working".
git rebase makes this easy and includes helpful instructions in the rebase message:
These lines can be re-ordered; they are executed from top to bottom.
It's clearly laid out if you follow along on the git docs and is as simple as re-ordering the lines so that the commits to be combined are together, and marking them as
For example, given a repo where these are all the commits:
$ git log --oneline 60d10b7 (HEAD -> example) finally figured out A e68f105 did something for C f8b495c hack related to A 2ce4970 did something for B 240ffc7 did something for A ff37364 initial
git rebase -i 240ffc7~1 will show you:
pick 240ffc7 did something for A pick 2ce4970 did something for B pick f8b495c hack related to A pick e68f105 did something for C pick 60d10b7 finally figured out A # Rebase ff37364..60d10b7 onto ff37364 (5 commands)
If you want to combine everything related to
A (the 3 lines above), you can just reorder them like below and mark the two commits to be merged as
pick 240ffc7 did something for A squash f8b495c hack related to A squash 60d10b7 finally figured out A pick 2ce4970 did something for B pick e68f105 did something for C # Rebase ff37364..60d10b7 onto ff37364 (5 commands)
Then just save and close, and when you're done 5 it will look like:
$ git log --oneline 179c64f (HEAD -> example) did something for C 092aa5f did something for B 79f744b did something for A ff37364 initial
"Unit" as in, if you're submitting a PR for a new feature, that PR would get "squashed" into 1 commit.
The PR itself should still have multiple commits to make it easy to follow along and review.
It's a personal preference and not everyone likes this. ↩
You can always dig back into the PR to see the back and forth if you really wanted. ↩
PR means "Pull Request" ↩
Probably because lately it's been after 3am when I'm working on this 😅 ↩
assuming you have no merge conflicts 🏆 ↩