In GitHub's merge queue, what is a merge group and what does CI actually test?
answer
- not your branch being tested
- base plus everything ahead of you
- a temporary read-only ref
- the event that starts the run
- several groups can be in flight
basics
~20 sA merge group is a temporary branch GitHub creates under gh-readonly-queue containing the base branch plus the queued changes up to and including one entry. CI runs against that ref via the merge_group event, and only a green result lets the entries land.
solid answer
~50 sWhen a pull request is queued, GitHub does not test your branch — it builds a **merge group**: a temporary ref named like `gh-readonly-queue/main/pr-42-<sha>` whose content is the base branch, plus the changes of every entry ahead of this one in the queue, plus this entry. GitHub then emits the **`merge_group`** event so CI runs against that ref, and the checks required on the target branch must report success for it. When they do and everything ahead has landed, GitHub merges using the branch's configured merge method and deletes the temporary ref. Because groups are **speculative**, GitHub can have several in flight at once, each assuming the ones ahead succeed. The practical consequence is that CI must be able to run for merge groups at all — a pipeline that only reacts to pull requests will never report on the group, and the entry will sit until it times out.
code
text · 3 linesgh-readonly-queue/main/pr-42-8f21c3a
gh-readonly-queue/main/pr-43-1d9b7e0
gh-readonly-queue/main/pr-47-c30fa55go deeper
Recall that the queue tests a temporary combined branch rather than your own, and that your pull request lands only when that combination is green.
Explain the composition of a merge group, the merge_group event that makes CI run against the temporary ref, and why the branch's required checks must report there.
Recognise the operational signatures — entries stuck building because nothing reports, or a queue that cannot land anything because its merge method conflicts with the branch's linear-history rule.
Own the correctness-versus-cost model of speculation: how many groups you allow in flight, and what a discarded speculative group costs when an earlier entry fails.
## The object being tested The key mental shift is that a queued pull request is no longer the unit of testing. The unit is the **merge group**: a commit that GitHub constructs to represent *the state the base branch will be in if everything up to this entry lands*. Concretely, GitHub creates a temporary branch in the repository whose name follows the pattern `gh-readonly-queue/<base-branch>/pr-<number>-<sha>`, containing: 1. the current base branch, 2. the changes from every queue entry ahead of this one, 3. the changes from this entry. Those refs are read-only to users — the name says so — and GitHub deletes them when the entry leaves the queue, whether it merged or failed. ## The signal CI reacts to GitHub emits a **`merge_group`** event when a group is created. That is the trigger CI must respond to; the required status checks configured on the target branch are then expected to report on the merge-group ref, exactly as they would report on a pull request head. Whether your automation reacts to the event is a pipeline-configuration question, but the platform contract is simple and worth stating precisely in an interview: *if the checks required on the branch never report for the merge group, the entry cannot pass and will eventually be removed.* That single sentence explains most first-day merge-queue failures. ## Speculation A queue that built one group at a time would give perfect correctness at the throughput of one CI run per merge — no better than requiring an up-to-date branch. The queue instead builds **speculatively**: with entries A, B, C queued, GitHub can construct and test `base+A`, `base+A+B`, and `base+A+B+C` concurrently. Each later group optimistically assumes the earlier ones will pass. If they do, all three land in order with roughly one CI duration of latency rather than three. If an earlier one fails, the groups built on top of it were based on a false assumption and must be discarded and rebuilt — which is where the CI cost of speculation is paid. Grouping is the other dimension: a group may contain more than one entry, so a single CI run validates several pull requests at once. That reduces runs but makes attribution harder when the run is red, since any one of the batched entries could be responsible. ## What GitHub does on success When a group's required checks pass and every entry ahead has already merged, GitHub merges the entries into the base using the **merge method configured for the queue** (merge commit, squash, or rebase). This is why a branch that also requires linear history must have the queue configured for squash or rebase — otherwise the queue produces exactly the commit shape the branch rejects, and nothing can land. ## What the merge group is not - **It is not your pull request branch.** Nothing is pushed to your branch, and its own checks are not what gates the merge. Your branch's checks still matter for the pre-queue gates (review, required checks before enqueueing), but the group is the final authority. - **It is not a permanent branch.** Do not build tooling that assumes `gh-readonly-queue/...` refs persist, and do not deploy from them. - **It is not a place for human intervention.** You cannot push a fix to a merge group; you fix the pull request and re-queue it. ## Observing it The queue view on the branch shows the entries in order, which group each belongs to, and each group's check status. A queued entry in a healthy repository moves through *queued → building → merged*; entries stuck in *building* with no check results are the signature of CI that does not run for merge groups, and entries that repeatedly enter and leave are the signature of flaky checks. ## Interview framing Define the merge group as base-plus-everything-ahead-plus-this-entry on a temporary `gh-readonly-queue` ref, name `merge_group` as the event that makes CI run against it, and state that the branch's required checks must report there. Add speculation as the reason several groups exist at once, and the merge-method detail as the thing that must line up with the branch's other rules. That is the full mechanism in four sentences.
- Can you push a fix directly to a gh-readonly-queue ref?No. Those refs are read-only and transient: GitHub creates one per merge group and deletes it when the entry leaves the queue, merged or not. The fix goes on the pull request branch, and the pull request is queued again, which places it at the back and produces a fresh group.
- Why can several merge groups exist for the same branch at once?Because the queue builds speculatively. With entries A, B and C queued, GitHub can test base+A, base+A+B and base+A+B+C concurrently, each assuming the ones ahead will pass. That parallelism is what recovers throughput; the cost appears only when an early entry fails and the groups above it must be discarded.
- Does the pull request's own check run still matter once it is queued?It matters for entry — review, approvals and the branch's pre-merge gates are evaluated before a pull request may join the queue. Once queued, the authority is the merge group's result, because that is the combination which will actually land. A green branch with a red group does not merge.
saying these in an interview costs you the question
- Thinks CI runs on the pull request branch while queued
- Believes the temporary queue branch is permanent
- Says the queue merges first and validates afterwards
- Assumes existing pull-request checks automatically cover merge groups
- Thinks only one merge group can exist at a time