Skip to content
starwed edited this page Apr 9, 2014 · 7 revisions

tl;dr: Use git rebase -i develop to squash commits.

It's pretty common for a PR to consist of multiple commits, either because you made several in your original work, or because of requested changes. But ideally, commits to the main repo are self-contained; Crafty should work and pass tests at any given commit.

Totally separate units of functionality are ok in separate commits, but bugfixes, adding docs, and intermediate versions should be squashed down.

There are two steps: first rewriting your local history, and then force pushing to override your github fork's history. This assumes your github fork is just a mirror of your local repo; see the note at the bottom for another approach.

How to squash commits

A convenient way to do this is via an interactive rebase. From the feature branch in question, the command is git rebase -i HEAD~N, where N is the number of commits you need to squash down. (You can read more about this in the git manual.)

You can also specify that you want to rebase the commits after you split off from a particular branch -- for Crafty this is probably develop. The command would then be git rebase -i develop.

The command will open up your editor with a list of commits and some instructions. If you used HEAD~3, it would look something like this:

pick f7f3f6d Added "Foo" component
pick 310154e Fixed bug with "Foo"
pick a5f4a0d Added documentation

# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

To squash down to a single commit, you want to replace every pick except the first one with squash. You'll then be given the opportunity to rewrite the commit message.

There's obviously more advanced things you can do here -- reordering commits, changing commit messages, etc. Again, see the docs if you need to know more! :)

Force pushing

This will rewrite your history. Because of this, you won't be able to do a regular push to your github repo -- you'll need to do a force push: git push feature-branch -f.

You might have read somewhere that you should never push to a public repo. But assuming you're the only one using it, your github fork of crafty isn't really public! It's just a mirror of your local, private repo.

The alternative, if you do have other folk using your repo, is to create a new branch before rebasing. Then you can create a new PR from that branch. The disadvantage here is that it makes browsing the github issue tracker more confusing -- it splits conversation of a particular patch over two (and maybe more!) PRs. Ideally github would let you merge issues, but since it doesn't, we have to deal with the existing system.