Commit bdad266c authored by Douwe Maan's avatar Douwe Maan

Support semi-linear history with rebasing and merge commits.

parent 201b0bb7
...@@ -179,7 +179,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -179,7 +179,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
return return
end end
if params[:ff].present? && !@merge_request.ff_merge_possible? if @project.ff_merge_must_be_possible? && !@merge_request.ff_merge_possible?
@status = :failed @status = :failed
return return
end end
...@@ -355,7 +355,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -355,7 +355,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def merge_params def merge_params
params.permit(:should_remove_source_branch, :commit_message, :ff) params.permit(:should_remove_source_branch, :commit_message)
end end
# Make sure merge requests created before 8.0 # Make sure merge requests created before 8.0
......
...@@ -247,8 +247,7 @@ class ProjectsController < ApplicationController ...@@ -247,8 +247,7 @@ class ProjectsController < ApplicationController
:approvals_before_merge, :approvals_before_merge,
:approver_ids, :approver_ids,
:issues_template, :issues_template,
:merge_requests_ff_only_enabled, :merge_method,
:merge_requests_rebase_enabled,
:merge_requests_template, :merge_requests_template,
:mirror, :mirror,
:mirror_user_id, :mirror_user_id,
......
...@@ -1037,4 +1037,32 @@ class Project < ActiveRecord::Base ...@@ -1037,4 +1037,32 @@ class Project < ActiveRecord::Base
PagesWorker.perform_in(5.minutes, :remove, namespace.path, temp_path) PagesWorker.perform_in(5.minutes, :remove, namespace.path, temp_path)
end end
end end
def merge_method
if self.merge_requests_ff_only_enabled
:ff
elsif self.merge_requests_rebase_enabled
:rebase_merge
else
:merge
end
end
def merge_method=(method)
case method.to_s
when "ff"
self.merge_requests_ff_only_enabled = true
self.merge_requests_rebase_enabled = true
when "rebase_merge"
self.merge_requests_ff_only_enabled = false
self.merge_requests_rebase_enabled = true
when "merge"
self.merge_requests_ff_only_enabled = false
self.merge_requests_rebase_enabled = false
end
end
def ff_merge_must_be_possible?
self.merge_requests_ff_only_enabled || self.merge_requests_rebase_enabled
end
end end
...@@ -9,9 +9,7 @@ module MergeRequests ...@@ -9,9 +9,7 @@ module MergeRequests
attr_reader :merge_request attr_reader :merge_request
def execute(merge_request) def execute(merge_request)
# Delete the ff param so we don't get into an infinite loop if it's present, if @project.merge_requests_ff_only_enabled && !self.is_a?(FfMergeService)
# since FfMergeService inherits from MergeService.
if params.delete(:ff).present?
FfMergeService.new(project, current_user, params).execute(merge_request) FfMergeService.new(project, current_user, params).execute(merge_request)
return return
end end
......
...@@ -3,22 +3,39 @@ ...@@ -3,22 +3,39 @@
Merge requests: Merge requests:
.form-group .form-group
.col-sm-offset-2.col-sm-10 = label_tag :merge_method_merge, class: 'control-label' do
.checkbox Merge method
= f.label :merge_requests_ff_only_enabled do .col-sm-10
= f.check_box :merge_requests_ff_only_enabled .radio
%strong Only fast-forward merging = label_tag :project_merge_method_merge do
= f.radio_button :merge_method, :merge, class: "js-merge-method-radio"
%strong Merge commit
%br %br
%span.descr The accept merge request button will only show when a merge without a merge commit is possible. %span.descr
A merge commit will be created for every merge, and merging is allowed as long as there are no conflicts.
.form-group.rebase-feature .radio
.col-sm-offset-2.col-sm-10 = label_tag :project_merge_method_rebase_merge do
.checkbox = f.radio_button :merge_method, :rebase_merge, class: "js-merge-method-radio"
= f.label :merge_requests_rebase_enabled do %strong Merge commit with semi-linear history
= f.check_box :merge_requests_rebase_enabled %br
%strong Rebase button %span.descr
A merge commit will be created for every merge, but merging is only allowed if the branch has been rebased.
This way you get a history that reads linearly (as with fast-forward merges), with the addition of merge commits.
%br %br
%span.descr Allows rebasing of merge requests before fast-forward merge. %span.descr
When the branch has not been rebased, the user is given the option to do so.
.radio
= label_tag :project_merge_method_ff do
= f.radio_button :merge_method, :ff, class: "js-merge-method-radio"
%strong Fast-forward merge
%br
%span.descr
No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch has been rebased.
%br
%span.descr
When the branch has not been rebased, the user is given the option to do so.
.form-group .form-group
= f.label :merge_requests_template, class: 'control-label' do = f.label :merge_requests_template, class: 'control-label' do
...@@ -69,12 +86,3 @@ ...@@ -69,12 +86,3 @@
:coffeescript :coffeescript
new UsersSelect() new UsersSelect()
mergeRequestsRebaseVisibilityCheck = ->
is_rebase_enabled = $("input#project_merge_requests_ff_only_enabled").prop("checked")
$(".rebase-feature").toggle(is_rebase_enabled)
mergeRequestsRebaseVisibilityCheck()
$("input#project_merge_requests_ff_only_enabled").change ->
mergeRequestsRebaseVisibilityCheck()
...@@ -19,12 +19,9 @@ ...@@ -19,12 +19,9 @@
= render 'projects/merge_requests/widget/open/merge_when_build_succeeds' = render 'projects/merge_requests/widget/open/merge_when_build_succeeds'
- elsif !@merge_request.can_be_merged_by?(current_user) - elsif !@merge_request.can_be_merged_by?(current_user)
= render 'projects/merge_requests/widget/open/not_allowed' = render 'projects/merge_requests/widget/open/not_allowed'
- elsif @project.merge_requests_ff_only_enabled - elsif @project.ff_merge_must_be_possible? && !@merge_request.ff_merge_possible?
- if @merge_request.ff_merge_possible?
= render 'projects/merge_requests/widget/open/ff_accept'
- else
= render 'projects/merge_requests/widget/open/rebase' = render 'projects/merge_requests/widget/open/rebase'
- elsif @merge_request.can_be_merged? - else
= render 'projects/merge_requests/widget/open/accept' = render 'projects/merge_requests/widget/open/accept'
- if @closes_issues.present? - if @closes_issues.present?
......
...@@ -30,10 +30,16 @@ ...@@ -30,10 +30,16 @@
= label_tag :should_remove_source_branch, class: "remove_source_checkbox" do = label_tag :should_remove_source_branch, class: "remove_source_checkbox" do
= check_box_tag :should_remove_source_branch = check_box_tag :should_remove_source_branch
Remove source branch Remove source branch
.accept-control.right .accept-control.right
- if @project.merge_requests_ff_only_enabled
Fast-forward merge without a merge commit
- else
= link_to "#", class: "modify-merge-commit-link js-toggle-button" do = link_to "#", class: "modify-merge-commit-link js-toggle-button" do
= icon('edit') = icon('edit')
Modify commit message Modify commit message
- unless @project.merge_requests_ff_only_enabled
.js-toggle-content.hide.prepend-top-default .js-toggle-content.hide.prepend-top-default
= render 'shared/commit_message_container', params: params, = render 'shared/commit_message_container', params: params,
text: @merge_request.merge_commit_message, text: @merge_request.merge_commit_message,
......
- status_class = @ci_commit ? " ci-#{@ci_commit.status}" : nil
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-requires-input' } do |f|
= hidden_field_tag :authenticity_token, form_authenticity_token
.accept-merge-holder.clearfix.js-toggle-container
.accept-action
- if @ci_commit && @ci_commit.active?
%span.btn-group
= button_tag class: "btn btn-create js-merge-button merge_when_build_succeeds" do
Merge When Build Succeeds
= button_tag class: "btn btn-success dropdown-toggle", 'data-toggle' => 'dropdown' do
%span.caret
%span.sr-only
Select Merge Moment
%ul.js-merge-dropdown.dropdown-menu.dropdown-menu-right{ role: 'menu' }
%li
= link_to "#", class: "merge_when_build_succeeds" do
= icon('check fw')
Merge When Build Succeeds
%li
= link_to "#", class: "accept_merge_request" do
= icon('warning fw')
Merge Immediately
- else
= f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do
Accept Merge Request
- if @merge_request.can_remove_source_branch?(current_user)
.accept-control.checkbox
= label_tag :should_remove_source_branch, class: "remove_source_checkbox" do
= check_box_tag :should_remove_source_branch
Remove source branch
.accept-control.right
Fast-forward merge without creating merge commit
= hidden_field_tag :merge_when_build_succeeds, "", autocomplete: "off"
= hidden_field_tag :ff, "1"
:javascript
$('.accept-mr-form').on('ajax:send', function() {
$(".accept-mr-form :input").disable();
});
$('.accept_merge_request').on('click', function() {
$('.js-merge-button').html("<i class='fa fa-spinner fa-spin'></i> Merge in progress");
});
$('.merge_when_build_succeeds').on('click', function() {
$("#merge_when_build_succeeds").val("1");
});
$('.js-merge-dropdown a').on('click', function(e) {
e.preventDefault();
$(this).closest("form").submit();
});
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
- should_remove_source_branch = @merge_request.merge_params["should_remove_source_branch"].present? - should_remove_source_branch = @merge_request.merge_params["should_remove_source_branch"].present?
%p %p
= succeed '.' do = succeed '.' do
- if @merge_request.merge_params["ff"].present? - if @project.merge_requests_ff_only_enabled
The changes will be fast-forward merged into The changes will be fast-forward merged into
- else - else
The changes will be merged into The changes will be merged into
......
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
= icon("spinner spin") = icon("spinner spin")
Rebase in progress&hellip; Rebase in progress&hellip;
%p %p
This merge request is in the process of being rebased, during which time it is locked and cannot be closed. This merge request is in the process of being rebased.
:javascript :javascript
$(function() { $(function() {
merge_request_widget.rebaseInProgress() merge_request_widget.rebaseInProgress()
}); });
- elsif !@merge_request.target_project.merge_requests_rebase_enabled || !can_push_branch?(@merge_request.source_project, @merge_request.source_branch) - elsif !can_push_branch?(@merge_request.source_project, @merge_request.source_branch)
%h4 %h4
= icon("exclamation-triangle") = icon("exclamation-triangle")
Fast-forward merge is not possible Fast-forward merge is not possible
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
= f.button class: "btn btn-reopen js-rebase-button" do = f.button class: "btn btn-reopen js-rebase-button" do
Rebase onto #{@merge_request.target_branch} Rebase onto #{@merge_request.target_branch}
.accept-control .accept-control
Fast-forward merge is not possible. Branch must be rebased first Fast-forward merge is not possible. Rebase the source branch onto the target branch to allow this merge request to be merged.
:javascript :javascript
$('.rebase-mr-form').on('ajax:send', function() { $('.rebase-mr-form').on('ajax:send', function() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment