Skip to content

Draft: Introduce merge methods that squash without merge commit

What does this MR do and why?

Solves #1822 and #355613.

This mr:

  • Introduces squashing_without_merge_commit feature flag.
  • Adds merge_requests_ff_when_squashing column to table project_settings. This column indicates whether to use fast-forward for squash merges. It is used only when squashing_without_merge_commit feature flag is enabled. Without that feature flag column projects.merge_requests_ff_only_enabled controls both regular and squash merges (same as before this MR). This column is back-filled in post-deploy from existing column projects.merge_requests_ff_only_enabled. Feature flag should only be enabled once the migration is done.
  • Adds handling of merge_requests_ff_when_squashing setting in both frontend (to hide merge commit message editor when merge_requests_ff_only_enabled is true) and backend (to perform fast forward squash when merge_requests_ff_only_enabled is true). This is used only when feature flag squashing_without_merge_commit is true.
  • Adds merge method Merge commit unless squashing that sets merge_requests_ff_only_enabled to false, merge_requests_ff_when_squashing to true and merge_requests_rebase_enabled to false. This means that it uses FF for squash, but not for regular merges. It does not require rebasing before merge. Visible only after enabling feature flag. This merge method can be used with merge trains.
  • Adds merge method Merge commit (unless squashing) with semi-linear history that sets merge_requests_ff_only_enabled to false, merge_requests_ff_when_squashing to true and merge_requests_rebase_enabled to true. This means that it uses FF for squash, but not for regular merges, and that rebasing is required before merge when source branch is not up-to-date with its target. Visible only after enabling feature flag. This merge method cannot be reliably used with merge trains, just like existing semi-linear one.
  • Adds new documentation page user/project/merge_requests/merge_methods. Before this MR, there wasn't any page that would have all merge methods explained. Currently, fast-forward is explained in https://docs.gitlab.com/ee/user/project/merge_requests/fast_forward_merge.html, and semi-linear history in https://docs.gitlab.com/ee/user/project/merge_requests/reviews/#semi-linear-history-merge-requests (which isn't a great place for it in my opinion) and regular merge is not explained. This new page focuses on comparing merge methods and showing images with example merge commit history.

Screenshots or screen recordings

image

Method Merge commit (unless squashing) with semi-linear history works similar to existing semi-linear history method, so rebase might be required before merging:

image

For both new methods with squash enabled it shows up as a fast-forward merge, and merge commit message editor is not shown:

image

With squash disabled it shows as a regular merge:

image

Those changes are compatible with the feature-flag restructured_mr_widget:

image

image

New merge methods documentation page (click to expand)

image

Database migrations

== 20220320021859 ProjectsSettingsAddMrFfWhenSquashing: migrating =============
-- add_column(:project_settings, :merge_requests_ff_when_squashing, :boolean, {:default=>false, :null=>false})
   -> 0.0024s
== 20220320021859 ProjectsSettingsAddMrFfWhenSquashing: migrated (0.0024s) ====

== 20220320024127 ProjectsSettingsBackfillMrFfWhenSquashing: migrating ========
-- transaction_open?()
   -> 0.0000s
-- execute("INSERT INTO project_settings (project_id, created_at, updated_at, merge_requests_ff_when_squashing, legacy_open_source_license_available)\nSELECT id, NOW(), NOW(), true, true\nFROM projects WHERE id BETWEEN 1 AND 28 AND merge_requests_ff_only_enabled\nON CONFLICT (project_id) DO UPDATE\n  SET updated_at = excluded.updated_at, merge_requests_ff_when_squashing = true\n")
   -> 0.0007s
== 20220320024127 ProjectsSettingsBackfillMrFfWhenSquashing: migrated (0.0354s) 

How to set up and validate locally

  1. Enable feature flag squashing_without_merge_commit, for example by using rails console and then Feature.enable('squashing_without_merge_commit');.
  2. Go to project settings, expand Merge requests section.
  3. Verify link to new documentation page in merge method selection (link with text Learn more).
  4. Choose Merge commit unless squashing as a merge method.
  5. Verify that for MRs with squash enabled it does not introduce a merge commit, but instead uses "fast-forward", just as git merge --squash would.
  6. Verify that for MRs with squash disabled it creates a separate merge commit.
  7. Repeat the verification for merge method Merge commit (unless squashing) with semi-linear history. That method should also require rebase before merge if target branch has new commits.

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Piotr Stankowski

Merge request reports