Care and keeping of pull requests, part v

03 Jul 2015

See first post disclaimer

Scenario: You have a series of commits on a development branch that you would like to include in a PR. Maybe you want to cherry-pick them onto a new branch, maybe you want to rebase, maybe you want to just submit. In any case, you’d rather have one big commit to _____ (cherry-pick, rebase, push) instead of the many small commits. It’s squash time! [1]

In what follows, we have a development branch blue-lightning with a series of small commits that we would like to squash together.

Squashing commits

Step 1: identify your end points

To squash commits together, you need to establish a range of commits that may be squashed. Just because a commit is the end point of this range doesn’t mean it will be squashed - this step is more about setting the outer bounds of what you’ll be able to squash together. [2]

One endpoint of the range (the newest commit) will always be the tip of your current development branch, which you indicate by checking out the branch.

$ git checkout blue-lightning

The other endpoint (the oldest commit), needs to be the commit preceding the oldest commit you want to squash. Suppose my commit history on blue-lightning looks like this:

$ git log --oneline
zzz Zap!
sss Zing! 
ooo Zoom! 
nnn Zounds!
bbb Yikes!

If I want to squash nnn with the commits following it, then my “oldest commit” endpoint should be bbb, as it precedes nnn.

Step 2: start the squashing process

To actually squash commits, you’ll be doing an interactive rebase[3], using the endpoint you chose above. From blue-lightning, run:

$ git rebase -i bbb

This should throw you into your text editor.


There are multiple ways of indicating your chosen endpoint in this command:

  • Use the actual commit value (shown above)
  • Use HEAD~1 notation (in the example above, bbb would be equivalent to HEAD~4
  • If your endpoint commit is the tip of another branch (like master), you can use the name of the branch.

Step 3: indicate which commits you want to squash together

In the text editor, there will be a list of the commits between your two endpoints. They should all be prefaced by the word “pick.” As the text in the editor should helpfully indicate, if you change the “pick” prefix to the word “squash”, git will try to squash those commits together. You should leave the oldest commit of the squash as “pick”, as that will be the commit that the others are squashed into. In our example, that will turn this:

pick nnn Zounds!
pick ooo Zoom! 
pick sss Zing! 
pick zzz Zap

into this:

pick nnn Zounds!
squash ooo Zoom! 
squash sss Zing! 
squash zzz Zap

Note that the commits are listed from oldest to newest, which is opposite of their order in git log.

Save and close the file. Moments later, your text editor will open again, with a second file allowing you to modify the commit message that will be attached to the new aggregate commit (the default is the message for the most recent commit of the aggregate). Save and close.

The end!

[1] I consider this a “bonus points” git practice. It’s usually too fussy for me, but has its moments of utility. So here we are.

[2] For the mathematically minded among you, this range of squashable commits will be a half-open interval of the form: (oldest commit, newest commit].

[3] From my limited reading, it sounds like interactive rebasing is the power-drill of git features, as opposed to poking around with the hammers and screwdrivers of git commit and git push (etc). I cannot, in any way, reverse-engineer my intuition to make git rebase the obvious choice for git-feature- that-does-everything.

how-to » git, collaboration, care and keeping of prs, math,

Recent Posts



Popular Tags

ACT (2) RCF (6) Software Carpentry (6) books (3) care and keeping of prs (6) collaboration (9) computing (13) culture (10) empowerment (6) family (2) gender (2) git (9) hope (2) language (3) lessons (4) math (8) mental health (2) movies (2) personal (5) problem solving (3) programming (9) science (2) self care (3) shell (2) teaching (11) true story (5) tutoring (2) work (12)