What's a Merge Queue and what is it good for?


TL;DR;

If you're short on time and you're fairly familiar with how Git works, this TL;DR; should be helpful. If not, the rest of the article explains everything step-by-step.

  • If you run your CI on the head of your feature branch and your feature branches are not required to be up-to-date with the target, then you really don't know if your feature branch is compatible with the target branch.
  • If you do require all feature branches to be up-to-date with the target, you end up wasting a lot of time and money.
  • Instead of merging your feature branches directly directly, you can add them to a queue (the Merge Queue). A separate system (Mergetastic) can then pick off branches from this queue, make sure they're up-to-date with the target branch, run tests on this up-to-date commit, and fast-forward merge. This way you're able to run the tests on the exact commit that will be added to your target branch before merging.
  • And if this system is smart enough (which Mergetastic is), then it can pick off multiple branches from the queue simultaneously and merge them all in one go using an octopus merge. This can save your team both time and money.

Introduction

A Merge Queue is exactly what it sounds like: it's a queue that you add your branch/Pull-Request to in order for it to be merged. But a valid follow-up question is: why is that useful? 

Aside from the obvious convenience of not having to wait for builds to pass in order to merge*, the big reason for using a Merge Queue is that it can help eliminate bad merges and save you both time and money. Let's look at a few examples to understand this better.

The possibility of a "bad merge"

Figure 1: Simple no-fastforward merge

The figure above shows a simple branch called my_branch that was branched off of the main branch a few commits back. Notice that there are ✅ attached to each of the commits. That's meant to show that there's even a CI system running for each new commit and that all of these commits have passed the tests. That's incredible!

Unfortunately, the CI system here only proves that each of the commits pass the tests. Even though the latest commits in both the main and the my_branch branches pass the tests, it is no guarantee that when my_branch is merged into the main branch, the resulting merge commit will also be able to pass the tests. That's because nothing has verified that the changes introduced by red commits are compatible with the changes introduced by the blue commits. Figure 2 illustrates this surprisingly common scenario.

Figure 2: Even though 2 divergent branches pass their tests, their merge commit can fail the same tests.

Forcing feature branches to be up-to-date with the target branch

But now you’re probably thinking that an easy fix for this would be to require everybody’s branches to be up to date with the target branch before merging. And you’re right, that would help. In fact, some platforms like Github have automated checks that prevent branches from being merged if they are not up to date with the master. But let’s take a look at that scenario for a medium sized team.

Figure 3: Many no-fastforward-able branches

Figure 3 above shows a relatively common scenario in a medium-sized team. There's one main branch and a whole bunch of other branches being worked on in parallel. They all diverge from the main branch at different points. In most medium-sized teams, you generally have more parallel branches than 3, but this should convey the point. Imagine setting up a rule that only branches that are completely up-to-date with the main branch can be merged. 

Naturally, everybody who's interested in merging their branch(es) goes ahead and merges the main branch into their branches. Let's assume that branch_2 was the first one to get merged into the main branch. As soon as that happens, the main branch advances, which means that branch_1 and branch_3 are out of date again! So now we get the complicated mess shown in Figure 4.

Figure 4: branch_2 gets merged into main, which causes the main branch to advance.

And because branch_1 and branch_3 are out of date again, they have to merge main back in again if they hope to get merged! So that complicates things again.

Figure 5: As soon an the main branch advances, every branch has to update

Notice how in the persuit of avoiding bad merges, a lot of unnecessary updates are happening. Devs have to constantly update their branches, which wastes their time. And the tests run on each of these merge commits unnecessarily leading to money being wasted. Many teams just accept bad merges as the cost of doing business, because this solution of forcing branches to be up-to-date with the target branch is too wasteful and there's no other alternative.

Many teams just accept bad merges as the cost of doing business, because this solution of forcing branches to be up-to-date with the target branch is too wasteful and there's no other alternative.

How Mergetastic solves this problem

Mergetastic makes this problem super-simple to solve. Let me show you how.

  • The devs just add their Pull Requests to the Merge Queue and walk away. That's it! They don't have to babysit their pull requests, making sure they're up-to-date with the target branch.
  • Mergetastic just takes all the pull requests in the queue and creates a single merge commit (an "octopus merge" in Git can merge arbitrary number of branches together). It assigns a mergetastic branch to this new merge commit. In Figure 6 below, the mergetastic-main branch points to this octopus merge.

Figure 6: Mergetastic solves this whole problem for you!

  • Your existing CI system runs the full set of tests for only the mergetastic branch. In Figure 6 above, your CI system runs the full test-suite on mergetastic-main. (For all the other branches, your CI system should still run the quick-and-cheap subset of the tests. See Best Practices with Mergetastic).
  • If the tests pass, the mergetastic build branch is fast-forward merged into the target branch. In plain English, if the tests for mergetastic-main in Figure 6 pass, that becomes the new "latest commit" (head) of the main branch. That's how you get to Figure 7. And you've saved yourself from unnecessarily building all those commits.

Figure 7: When mergetastic-main passes tests, it's fast-forward merged into main

  • But what happens if the tests don't pass? No worries! Mergetastic will go into divide-and-conquer mode. It’ll split the list of branches it’s trying to merge in half and try each of the halves independently to quickly and efficiently narrow down the list of PRs that can be merged.

In short, Mergetastic saves you from bad merges🙅🏽‍♂️ , it saves you time ⏱ , and it saves you money 💸.

So sign up today and start your 30-day free trial!

 

* Bitbucket already has a feature in beta for merging PRs when builds pass. Mergetastic is a lot more than that.

 

Next: Installing Mergetastic