GitLab: a merge refused or failed over squashing
GitLab squashes the commits of a merge request into one when the squash setting asks for it. When the setting requires squashing and the merge does not ask for it, or the squash itself fails, the merge does not happen. The merge API then answers only 422 Branch cannot be merged, and GitLab keeps the reason in the merge_error of the merge request, which is also the message shown in the merge request (GitLab source lib/api/merge_requests.rb and app/services/merge_requests/merge_service.rb, read October 28, 2026). The reasons:
This project requires squashing commits when merge requests are accepted. Squashing failed: The commits have conflicting changes. Squash the commits locally, resolve the conflicts, then push the branch. Squashing failed: Squash the commits locally, resolve any conflicts, then push the branch.
The squash options
- Of the project: Settings > Merge requests > Squash commits when merging, set by a Maintainer or Owner. Do not allow (
never): never squashed, and the option is not shown. Allow (default_off): allowed, cleared by default. Encourage (default_on): allowed and selected by default. Require (always): always squashed, and users cannot change it (GitLab docs Configure squash options for a project). The REST API shows it as thesquash_optionof the project. - Of a protected branch: a branch rule can have its own squash option, with the same four choices and Default, which removes it. For merge requests into that branch, it wins over the project setting (
ee/app/models/ee/merge_request.rb). It came in GitLab 17.9 behind a flag, was on by default from 17.10, and has had no flag since 17.11. In GitLab Premium and Ultimate it is there for all branch rules; in GitLab Free only for the All branches rule, which is the project setting (Edit squash commits option). Thesquash_optionof the project does not show it.
Why the merge did not happen
- "This project requires squashing commits when merge requests are accepted.": the option that applies is Require, and neither the merge request (its Squash commits when merge request is accepted checkbox,
squash) nor the merge (squash=true) asks for a squash. GitLab checks this before it merges (missing_required_squash?inapp/models/merge_request.rb,app/services/merge_requests/merge_strategies/from_source_branch.rb). The merge API sets the squash of the merge request only when the request sendssquash=true. The sentence says "this project" also when it is the target branch that requires squashing, so a tool that reads only the project setting sees Allow and leaves squash off. - "Squashing failed: The commits have conflicting changes.": GitLab squashes the commits on the server, and the commits of the source branch conflict with each other on the way (
app/services/merge_requests/squash_service.rb). The other "Squashing failed" sentence is for any other error during the squash. - Do not allow does not fail a merge: GitLab merges without squashing, even when the merge sends
squash=true(squash_on_merge?is false).
How to see the setting that applies
- REST API: read the merge request.
squash_on_mergealready takes the project and the target branch into account;squashis only the checkbox.squash_on_mergetrue withsquashfalse means that squashing is required. After a failed merge,merge_errorhas the reason. - GraphQL:
squashOnMerge, andsquashReadOnly, which is true when the option that applies is Require or Do not allow. The squash option of each branch rule isbranchRules { squashOption { option } }, marked as an experiment since GitLab 17.9.
curl -H "PRIVATE-TOKEN: your-token" "https://gitlab.com/api/v4/projects/group%2Fproject/merge_requests/42"
query {
project(fullPath: "group/project") {
mergeRequest(iid: "42") { squash squashOnMerge squashReadOnly mergeError }
branchRules { nodes { name squashOption { option } } }
}
}
What to do
- Squashing is required: merge with
squash=true, or select the squash checkbox of the merge request and merge again. To change the rule, a Maintainer or Owner edits the squash option of the branch rule of the target branch, or of the project. - The commits conflict when squashed: squash the commits locally (for example
git rebase -ionto the target branch), resolve the conflicts, push the branch, then merge again. - Other squash errors: GitLab asks for the same: squash the commits locally, resolve any conflicts, then push the branch.
For the other answers of the merge API (405, 409, 401, 400), see why GitLab refused the merge.
GitLab merge requests in IntelliJ IDEA
Merge Request Inbox for GitLab, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, merges a merge request from the IDE. Its merge dialog reads how GitLab will squash the merge request (squashOnMerge, squashReadOnly), so the squash setting of a protected target branch counts too: when squashing is required it selects the squash checkbox and locks it, when it is not allowed it clears and locks it. When a merge fails with 422, it shows the reason GitLab kept (merge_error), such as "This project requires squashing commits when merge requests are accepted." Before version 1.0.19, it went by the project setting only. Reading is free; approving, commenting and merging are Pro (US$1.50 a month, with a 30-day trial).
GITLAB is a trademark of GitLab Inc.; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with or endorsed by GitLab Inc. or JetBrains.
More: GitLab merge refused (405, 409, 422) · GitLab auto-merge refused (405) or canceled · GitLab rebase refused or failed (403, 409) · GitLab 429 "Retry later" (rate limits) · GitLab "compare_timeout": true (diff limits) · GitLab merge request plugins for IntelliJ IDEA, compared · 日本語