Out of the three ways you can merge GitHub pull requests (“Merge”, “Squash and merge”, or “Rebase and merge”), “Squash and merge” has the best developer experience.
Let’s see why.
One idea is one commit
Ideally a pull request is one logical change, like fixing a bug, adding a new view, or refactoring logic. Since each pull request is “one idea” we want “one commit” representing that change after merge (see “Recommendations on Revision Control” for a longer discussion).
In reality a large pull request may be one idea, but since large pull requests aren’t easily reviewable we need break up the change into smaller, reviewable pieces (see “Make small changes”).
“Squash and merge” makes this workflow easy and creates a single commit on merge for your pull request.
In contrast, workflows like “Merge” or “Rebase and merge” allow multiple commits for a single pull request to be merged. Manual squashing and force pushing commits is required to ensure you only merge one commit — that’s more work than “Squash and merge”!
GitHub hates force push
GitHub has a couple nice features to make code reviewers’ lives easier. Reviewers receive a helpful “New changes since you last viewed” marker when new commits are added to a pull request. A reviewer can also mark a file as viewed and see an indicator when that file has been updated by new commits. Force-pushing breaks these features.
The “Merge” and “Rebase and merge” workflows require force pushing, but “Squash and merge” doesn’t. Developers only add new commits with “Squash and merge”, which the GitHub UI handles flawlessly.
For GitHub we shouldn’t force push as it impairs code review.
Regardless of how a developer creates commits for their pull request, with “Squash and merge” their changes will be squashed into a single commit on merge.
“Squash and merge” frees the developer to make commits as they please. They don’t need to worry about commit messages or making orderly commits. They can fix tests, add GitHub pull request suggestions, and address pull request feedback without concern for their individual commits.
A huge caveat here is the actual commit message format. With “Squash and merge” GitHub will combine all the commit messages associated with a pull request into a single commit. This results in commit messages that aren’t very useful.
* add new share menu * adjust UI layout * fix test * fix test for real * address feedback * fix lint * fix formatting
We can do better!
Pull request titles and bodies are well written and easily editable so let’s use them for our commit messages. We could manually copy and paste this information on merge, but we’re developers, we can automate this!
Kodiak (I built this) can automatically merge pull requests and use the pull request title and body as the commit message. With Kodiak setup our commit messages will look as great as our pull requests.
Pull requests are reviewable, not commits
When reviewing a GitHub pull request, a reviewer sees a comparison between the pull request branch and the target branch. While you can inspect the individual commits of a pull request, a review is added for the code change as a whole, not the individual commits that sum to that change.
In a GitHub-centric world it’s better to focus on making reviewable pull requests, because pull requests are reviewable, not commits.
Squashing is easy
“Squash and merge” is great because it requires less work from the developer.
With “Squash and merge” we can focus on the pull request, not the commits that compose it. It’s easier to update a pull request body than to update a commit. GitHub “just works” with “Squash and merge”.