GitLab merge trains: how they work, and why a merge request leaves the train

By Melih Toksari, developer of MergeBell · Updated · 5 min read

Short answer

A merge train queues merge requests for the same target branch and tests each one combined with every merge request ahead of it, so changes that pass alone but break together are caught before they merge, unless someone skips the train. It needs Premium or Ultimate, merge request pipelines and merged results pipelines; a Maintainer turns it on in Settings › Merge requests. Select Merge, or Set to auto-merge while a pipeline runs, to join the train, and Cancel auto-merge to leave it. If a merge request's pipeline fails, GitLab drops it and restarts the pipelines behind it, and its Activity says why. A train runs up to 20 pipelines at once by default, which a project can change since GitLab 19.0, and since 19.3 a project can make the train mandatory.

Two merge requests each pass their pipeline, both merge, and the default branch breaks. Each was tested against the target branch, but not against the other. A merge train fixes that by testing merge requests in the order they will merge. Here is how merge trains work in GitLab 19.5, how to turn them on, and why a merge request falls off one.

How a merge train works

Add merge requests A, B and C to a train, in that order, and GitLab runs three pipelines in parallel:

  1. A, combined with the target branch.
  2. A and B, combined with the target branch.
  3. A, B and C, combined with the target branch.
  • Each one merges when its own pipeline has passed and every merge request ahead of it has merged.
  • If B’s pipeline fails, B leaves the train, A carries on, and C’s pipeline is canceled and started again as A and C together.
  • The pipelines are merged results pipelines: they run on a merge commit GitLab builds, not on the last commit of your branch.
  • Premium and Ultimate only, on GitLab.com, GitLab Self-Managed and GitLab Dedicated.

Turn merge trains on

You need the Maintainer role, and the project needs merge request pipelines. Without them, GitLab’s docs warn, merge requests may become stuck in an unresolved state, or their pipelines may be dropped. A common way to get them:

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Then:

  1. In the project, select Settings › Merge requests.
  2. Under Merge options, make sure Enable merged results pipelines is selected, and select Enable merge trains.
  3. Select Save changes.

Two more settings in the same section matter here:

  • Maximum parallel pipelines per merge train (GitLab 19.0 and later): 20 by default, the limit trains had before the setting existed. Merge requests beyond it wait for a free slot, and 1 runs them one at a time.
  • Merge train enforcement (generally available in GitLab 19.3): Allow bypass, the default, lets anyone who can merge skip the train. Enforce for all users sends every merge through it, and Enforce with Owner override lets Owners and administrators skip it for single merge requests.

Join the train, and see the queue

  • Join: select Merge when no pipeline is running, or Set to auto-merge when one is. The first merge request starts the train: “A new merge train has started and this merge request is first in the queue.” Later ones see their place, such as “This merge request is #2 of 3 in queue.”
  • See the queue: in Code › Merge requests, select Merge trains above the list, or follow View merge train in a merge request’s widget. It shows the merge requests waiting and the ones the train has merged.
  • New threads don’t stop it. Once a merge request is on the train, a new thread doesn’t take it off, even with All threads must be resolved turned on.

Leave the train, or skip it

  • Leave: select Cancel auto-merge on the merge request, or the ✕ next to it in the merge train details. The pipelines of the merge requests behind it start again.
  • Merge immediately: for a fix that can’t wait. It merges at once, cancels the train’s pipelines and starts a new train with every merge request that was waiting, each with a new pipeline. It can use a lot of CI/CD resources, and it may be missing with fast-forward merges when the source branch is behind the target branch.
  • Merge without restarting the train: an experiment. With Merge immediately without restarting the merge train selected in the merge options, a merge request can merge with Merge now and don’t restart train, or through the merge requests API with skip_merge_train=true, and the train carries on. It doesn’t work with fast-forward or semi-linear merges, and nothing checks that change against the merge requests on the train.
  • [skip ci] in the title: since GitLab 19.5, it takes the merge request off the train, because a skipped pipeline isn’t a successful one. See how to skip a GitLab CI pipeline.

Why a merge request was dropped

GitLab drops a merge request from the train when it can no longer merge:

  • its merge train pipeline failed;
  • it was marked as a draft or closed;
  • its source branch got new commits;
  • a merge check failed, such as a merge conflict;
  • its changes couldn’t be combined with those of the merge requests ahead of it;
  • the merge didn’t finish in time, or something unexpected went wrong.

The merge request’s Activity says which, in a note like “name removed this merge request from the merge train because …”. GitLab also adds a To-Do for the person who added it.

The note goes on to say What to do
the merge could not be completed. Merge request is not mergeable. Explanation: … Fix what follows “Explanation:”, a failed merge check such as the pipeline, then add it again.
the merge train pipeline could not be prepared: Failed to create merge commit … Usually its changes conflict with a merge request ahead of it. Rebase, resolve the conflicts, then add it again.
the merge train pipeline could not be prepared: merging commits: merge: there are conflicting files. Conflicts in: … The same, with up to 10 of the conflicting files named.
the merge did not complete in time. Add it again. If it keeps happening, ask your administrator.
an unexpected error occurred. Correlation ID: … Give the ID to your administrator or GitLab Support, then add it again.

Things that trip people up

  • A failed merge train pipeline can’t be retried. The merged result it tested is now out of date, so add the merge request to the train again for a new pipeline. For flaky jobs, the retry keyword retries them inside the train, and a job that passes on a retry keeps its merge request on.
  • No Merge or Set to auto-merge button? With Pipelines must succeed on and a failed latest pipeline, the merge checks show “Pipeline must succeed.” and neither button appears. Retry the job, run a new pipeline from the Pipelines tab, or push a fix. The other blockers are in why can’t I merge my GitLab merge request?
  • Bots get 405 Method Not Allowed when the train is enforced and they merge through the API without auto_merge=true. With it, the merge request joins the train instead; for Renovate, turn on platformAutomerge. Scripts can add a merge request with the merge trains API, POST /projects/:id/merge_trains/merge_requests/:merge_request_iid, and take one off with POST /projects/:id/merge_requests/:merge_request_iid/cancel_auto_merge, new in GitLab 19.5 (older versions use cancel_merge_when_pipeline_succeeds).
  • Auto-merge doesn’t skip the train. With merge trains on, auto-merge is how a merge request joins it.

On your phone

When GitLab drops a merge request you added, the To-Do it creates shows in MergeBell’s inbox as Left the merge train, and it arrives as a push, “Removed from the merge train”, like every new To-Do: free and checked every five minutes. The reason is in the merge request’s Activity. More on what creates To-Dos in the GitLab To-Do List guide.

Frequently asked questions

What is a merge train in GitLab?

A queue of merge requests that target the same branch. GitLab tests each one combined with every merge request ahead of it, in pipelines that run in parallel, and merges them in order, so changes that pass alone but break together are caught before they reach it. Merge trains are a Premium and Ultimate feature.

How do I add a merge request to a merge train?

With merge trains turned on, select Merge when no pipeline is running, or Set to auto-merge when one is. The merge request widget then shows its place, for example "This merge request is #2 of 3 in queue."

Why was my merge request removed from the merge train?

Its merge train pipeline may have failed. Other causes are being marked as a draft or closed, new commits on its source branch, a failed merge check, or changes that conflict with merge requests ahead of it. The merge request's Activity has a note that says "removed this merge request from the merge train because" and gives the reason, and GitLab adds a To-Do for the person who added it.

Can I retry a failed merge train pipeline?

No. Once the merge request is dropped, the merged result that pipeline tested is out of date, so add the merge request to the train again, which starts a new pipeline. For jobs that fail now and then, the retry keyword retries them inside the train, and a job that passes on a retry keeps the merge request on it.

How do I skip the merge train?

Select Merge immediately on the merge request. It merges at once and restarts the pipelines of every merge request on the train, so keep it for urgent fixes. Since GitLab 19.3, a project can enforce the merge train, which hides Merge immediately for everyone, or for everyone but Owners and administrators.

Sources

Checked against these pages on 30 October 2026. GitLab changes quickly — if something here no longer matches, tell us and we will fix it.

Do this from your phone with MergeBell

Free for the whole review loop: the To-Do inbox, diffs and line comments, approve and merge, pipelines with retry, and push alerts for your To-Dos. Works with gitlab.com and self-managed GitLab 16.0+.

Get MergeBell for iPhoneGet MergeBell for Android

On the App Store for iOS 26 or later and on Google Play for Android 12 or later. An independent app, not affiliated with GitLab Inc.