How to Pick your GitHub Merge Methods

How to Pick your GitHub Merge Methods

Julien Danjou

GitHub merge methods can be tough to choose correctly. Implementing the wrong merge method on your project's main branch can detract from your team's ability to follow along and contribute.

In other words, using the wrong merge method for the occasion defeats the entire purpose of Git—namely, seamless collaboration and documented versioning. This article should help you make the right choice of GitHub merge method from now on.

Differences between GitHub merge methods

Each merge method available on GitHub has different pros and cons. Learn these, and you'll understand precisely why you should (or shouldn’t) use them.

Merge

Merging a feature branch with your main branch is the simplest and safest way to incorporate the latest changes from the main branch into the feature branch. When you merge two branches, a merge commit signals that one has been incorporated into the other at a given point in time. This provides context and a clear history of how your project's code has developed. By default, GitHub includes the pull request title and number in the merge commit message. That makes it easy to get back to the original discussion that led to the pull request being merged.

A merge commit has (at least) 2 parents' commits.

However, merging might not be ideal for all cases.

Whenever you merge without fast-forward — and GitHub never merges with fast-forward — you pollute your project's history with a new merge commit. This can lead to a lot of very messy branches as your project develops and additional contributors pile on fresh changes. Both squashing and rebasing can help with this when you need to preserve your project's clarity.

What happens when you merge.

Rebase and merge

When merging may cause undue confusion among your teammates, rebasing and merging become a more attractive option. Rebasing effectively places your branch at the very tip of the branch you’re merging it with, yielding a clean history that’s fairly easy to understand.

A pull request with a single commit rebased and merged.

Unfortunately, rebasing does have its downsides.

Whenever you choose to rebase a branch onto another one, all commits on your feature branch are applied on top of the target branch. This is fine as long as the pull request commit history makes sense. If it is essentially composed of “fix-up” commits, that will pollute your project history. Worst, having this kind of confusing history made up of many work-in-progress commits makes it very hard to use tools like git bisect to find the root cause of a bug as those half-baked commits are usually not working or testable.

Reverting a rebased and merged pull request might also be more difficult, as you’ll have to revert multiple commits potentially.

If you want (or don't want) to allow this method on your repository, you can enable or disable it.

Squash and merge

Squashing commits and merging them can help tremendously in preserving the legibility of your branches. In contrast with a regular merge operation, squash merges only apply one commit on the target branch, consisting of all the commits from the pull request squashed together. These types of merges leave out the actual commit history entirely, keeping your target branch clean and easy to follow.

A squash pull request made of multiple commits, originally.

Squash merges also differ greatly from rebase merges. Instead of replaying individual commits one at a time on the target branch, these merges make a single commit on it for all merged changes. This can be beneficial for some use cases and detrimental for others. Thus, even squash merges are not ideal for every situation.

They help to make sure the history is clean and that the git history is bisectable. However, the default commit message used by GitHub is based on the combination of the messages from all the commits of the pull request, which can be very verbose and contain useless information. Automating the merge and leveraging Mergify’s commit_message option is actually a life savior in this regard: it can instead use the title and body of the pull request as the commit message.

As for the others merge method, you can allow or disallow this method on a per-repository basis.

When to use each GitHub merge method

The methods mentioned above are all useful in their own ways and for different reasons. Now that you know why you might want to use them, you should learn when each one is your team's best bet.

Merge Rebase Squash
Easily bisectable ⚠️ ⚠️
Easily revertable ⚠️
Track authorship of original commits code

⚠️ = depends on how the commit history is built

Merge when alternatives would cause greater confusion

If your commit history needs to be preserved for future reference on the main branch or target branch you’re merging into, then a simple merge might work best.

Rebasing would keep your commit history linear while squashing and merging would also condense it and obfuscate the details. A normal merge will pull details on commit ancestry and both affected branch tips into the generated commit, making tracing your work in detail much easier to do later on.

Use rebase and merge to create a linear history

Rebasing can be fantastic for simplifying your branch's history of commits for future reference. However, because it includes all commits, you should exercise a bit of restraint in applying this option if your pull request history is not perfectly clean.

Squash and merge to create linear history without rewriting commits

When you want to keep your project's main branch clean, but you can’t risk contaminating its history with rewritten commits, then you may need to squash your next merge. Squashed merges are perfect for simplifying your commits on public branches without affecting other contributors' work.

Keep in mind that your squashed commit is a condensed version of your feature branch.

Merge with confidence and consistency

Much like pulling and committing, merging is essential to your workflow on GitHub. Getting it right is non-negotiable and well worth the effort for both your team and your project.

Providing a consistent workflow to your engineering team is key to the success of your project. With Mergify, you can fully automate pull request merging and make sure that your repository's commit history says consistent with your policy.

To learn more about merging and how automation can play a pivotal role in lightening your daily workload, reach out to our team at Mergify.