What is a merge queue?
A merge queue is a system that tests approved pull requests in order, each combined with the main branch and the changes ahead of it. A pull request merges only when its checks pass on that combination. GitHub calls the feature a merge queue, and GitLab calls it a merge train.
A merge queue closes a gap in continuous integration (CI). In GitHub Actions, a check on a pull request tests the branch merged with the main branch as it stood when the check ran. Once other pull requests merge, that result is stale, and two green pull requests can break the main branch together.
GitHub's documentation says its merge queue gives the same protection as requiring each branch to be up to date, without making authors update branches by hand. A queue can be built into the code host or run by a merge queue bot, which usually takes commands from a label or a comment.
Work that starts from the main branch inherits a break there, so other people's checks fail until someone fixes the break. In a CI/CD pipeline with continuous delivery, a broken main branch also holds up the next release.
How does a merge queue work?
Two green branches break the main branch together when their changes merge cleanly as text but not as behavior. Git reports a conflict when both branches edit the same or adjacent lines of a file. If one branch renames a field and the other adds a line that reads the old name, Git merges both, and the combined code fails. This is a semantic conflict, which no check on one branch alone can catch.
On GitHub, a merge queue tests that combination in these steps:
- A person with write access clicks "Merge when ready," and the approved pull request joins the queue once its required checks pass.
- The queue creates a temporary branch, called a merge group, that holds the current main branch, the changes ahead in the queue, and this pull request.
- CI runs the required checks on that group, while groups for later pull requests run in parallel.
- When the checks pass for its group and the groups ahead, the queue merges the pull request into the main branch.
- When the checks fail, the queue removes the pull request and rebuilds each group behind it without that change.
A GitHub Actions workflow must list the merge_group event to run the required checks on merge groups. Without it, the checks never report, and the merge fails. After the status check timeout, the queue treats missing checks as failed. In GitLab's merge trains, a failed pipeline likewise removes its merge request and restarts the pipelines queued after it.
What is an example of a merge queue?
Here is an illustrative example. Acme Co. sells furniture online, and its main branch requires a merge queue. Its CI workflow runs on both events:
on:
pull_request:
merge_group:
A developer at Acme asks a coding agent to "Let customers edit their delivery address during checkout." The change meets a teammate's change in the queue:
- The agent's address code copies
order.itemsinto the saved order. Its checks pass, and a reviewer approves it. - A teammate's pull request renames
order.itemstoorder.lines. It passes the same hour. - The rename joins the queue first, then the address change.
- The queue tests
mainwith the rename, andmainwith both changes, in parallel. - The first group passes. In the second, the cart test expects 2 items and receives 0. The address saved, but the cart emptied.
- The queue merges the rename and removes the address change, whose line still reads
order.items. - The developer sends the log to the agent, which updates its branch from
mainand copiesorder.linesinstead. The change merges on its next pass.
Git reported no conflict, because the rename changed no line next to the agent's added line. Without the queue or a rule that branches be up to date, both would have merged green and broken main. This example is simplified. A real project would also run end-to-end tests on each group.
What changes when a coding agent writes the code?
Coding agents raise the number of approved pull requests that wait for the main branch at once. Branches from parallel coding agents often first run together in the queue, because each agent worked without the others' changes. Background coding agents add bursts, e.g. several pull requests opened overnight and approved together the next morning.
Requiring branches to be up to date handles a burst poorly. Each merge makes every waiting pull request stale, so its author updates the branch and the checks run again. That extra load is one reason CI becomes the bottleneck for AI-written code. A queue tests each waiting change once, in order, unless a change ahead of it fails or jumps the queue.
A queue failure reaches the agent only if someone sends it back. A practical adjustment is to return each removal to the agent that wrote the change, with the failing group's log and the changes that were ahead of it. Then check the agent's next diff, because the agent can make the group pass by editing the failing test instead of its own code. Smaller agent changes also make a removal cheaper to fix, one more reason to limit pull request size.
What are the limits of a merge queue?
A merge queue has these limits:
- It checks only what the required checks test. A passing group shows that those checks passed, not that the software works, so the queue extends regression testing to combined changes only for behavior the suite covers.
- Flaky tests remove correct changes. A flaky test that fails a group sends a correct pull request back and restarts each group behind it.
- It costs runner time and waiting. Each group reruns the required checks after the pull request's own run. On GitHub, a pull request that jumps the queue rebuilds each group in progress.
- It checks code, not intent. Two changes can pass together and still disagree about what the software should do, so a person has to review a pull request.
A team needs a merge queue when its main branch breaks after merges that each passed, or when authors keep updating stale branches. Both are common once several agents open pull requests each day. A team that merges a few a day can usually require branches to be up to date instead.
How is a merge queue different from required status checks?
Required status checks are named check results that a branch rule requires to pass before a pull request merges. Each one is a blocking check, because its failure stops the merge. A merge queue decides which code those checks run on, and in what order pull requests merge. On GitHub, an administrator turns the queue on with the "Require merge queue" branch setting, and the queue runs the same required checks on each merge group.
Required checks alone can pass on a stale base. GitHub's strict setting, "Require branches to be up to date before merging," closes that gap by making each author update the branch and wait for the checks again. A queue does that work in order, without the author. On GitHub.com, merge queues work in public organization repositories and in private ones on GitHub Enterprise Cloud. GitHub Enterprise Server offers them in any organization repository.
FAQs
What is a GitHub merge queue?
A GitHub merge queue is the merge queue built into GitHub for protected branches. An administrator turns it on with the "Require merge queue" setting in a public organization repository, or in a private one on GitHub Enterprise Cloud or Server. People then add approved pull requests with "Merge when ready."
If two branches pass their tests, will the merge pass?
Two branches that pass their tests alone can still fail once both merge. Git combines them as text, and a change in one branch, e.g. a renamed field, can break an added line in the other. A merge queue tests that combination before it reaches the main branch.
How do you manage a pull request merge queue?
Managing a pull request merge queue starts with the CI workflow, which must run the required checks on each merge group. An administrator then sets how the queue behaves, e.g. its status check timeout. When the queue removes a pull request, its author fixes the failure and adds it again.
How is a merge queue different from CI?
A merge queue is a step within CI, not a replacement for it. CI usually runs checks on each push and pull request. The queue runs the final checks on the main branch combined with the changes ahead, and it merges only the pull requests that pass.