Keep auto-merge when automatic rebase handles target branch
What does this MR do and why?
When a project's merge method requires the source branch to sit on top of the target
(Fast-forward merge or Merge commit with semi-linear history), pushing to a target branch
aborts any pending auto-merge on the merge requests targeting it, and opens a to-do for the author.
See RefreshService#abort_ff_merge_requests_with_auto_merges.
That behaviour assumes the author now has a rebase to perform by hand, which a pending auto-merge
cannot do for them.
That assumption does not hold when the project has Enable automatic rebase prior to merge turned
on. In that case
FromSourceBranch#use_create_ref_service?
routes the merge through
MergeRequests::CreateRefService,
which rebases onto the target and then fast-forwards it. The merge checks still gate the merge.
Mergeability::CheckRebaseStatusService
already exempts these projects from the "source branch must be rebased" merge check for exactly this
reason. The
abort
never received the matching exemption, so a project with automatic rebase turned on still has its
auto-merges cancelled for a condition GitLab resolves on its own, and the author has to re-arm
auto-merge by hand every time the target branch moves. This MR aligns the two.
Deliberately unchanged:
- Merge train strategies. The loop already skips anything other than
merge_when_checks_pass, and merge trains are mutually exclusive with that strategy. - Aborting when the source branch is updated (
#abort_auto_merges). That is a different condition and remains correct.
Considerations:
- Behind a feature flag.
retain_auto_merge_with_automatic_rebase, typegitlab_com_derisk, disabled by default. The flag is checked after the project setting, so projects without automatic rebase before merge do not pay for a flag lookup on every push to a target branch. - Automatic rebase does not re-run CI/CD. A retained auto-merge can therefore merge a rebased result that no pipeline has tested. That is inherent to the existing feature rather than new here, and is already documented under automatic rebase before merge, but it is the main behavioural consequence of this change.
- No changelog trailer, because the change is behind a flag that is disabled by default. One belongs in the merge request that removes the flag.
References
- Related to #463356. That issue is broader: it asks for auto-merge to survive automatic retargeting, which this MR does not address. This MR fixes only the fast-forward/semi-linear abort, which stands on its own as an inconsistency with the mergeability check.
- Feature flag rollout issue: #611435
- Automatic rebase before merge: https://docs.gitlab.com/user/project/merge_requests/methods/#automatic-rebase-before-merge
Screenshots or screen recordings
No user interface changes.
How to set up and validate locally
-
In a project with a repository, go to Settings > Merge requests, and:
- Set Merge method to Merge commit with semi-linear history (or Fast-forward merge).
- Select Enable automatic rebase prior to merge.
-
In the rails console, enable the feature flag for that project:
Feature.enable(:retain_auto_merge_with_automatic_rebase, Project.find(<project_id>)) -
Create a merge request from a feature branch, and set it to auto-merge.
-
Push a new commit to the target branch, so the source branch falls behind.
-
Observe the merge request:
- With the flag disabled: auto-merge is cancelled, with the system note
aborted the automatic merge because target branch was updated, and a to-do for the author. - With the flag enabled: auto-merge stays active, and the merge request merges once its checks pass, rebasing at merge time.
- With the flag disabled: auto-merge is cancelled, with the system note
Specs:
bundle exec rspec spec/services/merge_requests/refresh_service_spec.rb -e abort_ff_merge_requests_with_auto_mergesMR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.