diff --git a/CHANGELOG b/CHANGELOG
index 981fd0e77abfadb8ebe6a0cc724110dd165f5310..2e5cd78c8a8a7c9bf099c519fecf9e6d4ab2a1bc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+v 6.5.1
+  - Fix branch selectbox when create merge request from fork
+
 v 6.5.0
   - Dropdown menus on issue#show page for assignee and milestone (Jason Blanchard)
   - Add color custimization and previewing to broadcast messages
diff --git a/VERSION b/VERSION
index f22d756da39d4c5f688b56060df98ea326cc0376..13673ab4fa39960e175d96c11b917fb90b53c574 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.5.0
+6.5.1-001
diff --git a/app/assets/stylesheets/sections/diff.scss b/app/assets/stylesheets/sections/diff.scss
new file mode 100644
index 0000000000000000000000000000000000000000..eb272f20f40c23d5b1e473b85bd642c70f5ad27f
--- /dev/null
+++ b/app/assets/stylesheets/sections/diff.scss
@@ -0,0 +1,350 @@
+.diff-file {
+  border: 1px solid #CCC;
+  margin-bottom: 1em;
+
+  .diff-header {
+    @extend .clearfix;
+    background: #DDD;
+    border-bottom: 1px solid #CCC;
+    padding: 5px 5px 5px 10px;
+    color: #555;
+
+    > span {
+      font-family: $monospace_font;
+      font-size: 14px;
+      line-height: 2;
+    }
+
+    .diff-btn-group {
+      float: right;
+
+      .btn {
+        background-color: #EEE;
+        color: #666;
+        font-weight: bolder;
+      }
+    }
+
+    .commit-short-id {
+      font-family: $monospace_font;
+      font-size: smaller;
+    }
+
+    .file-mode {
+      font-family: $monospace_font;
+    }
+  }
+  .diff-content {
+    overflow: auto;
+    overflow-y: hidden;
+    background: #FFF;
+    color: #333;
+    font-size: 12px;
+    .old {
+      span.idiff {
+        background-color: #FAA;
+      }
+    }
+    .new {
+      span.idiff {
+        background-color: #AFA;
+      }
+    }
+
+    table {
+      width: 100%;
+      font-family: $monospace_font;
+      border: none;
+      margin: 0px;
+      padding: 0px;
+      td {
+        line-height: 18px;
+        font-size: 12px;
+      }
+    }
+
+    .text-file-parallel div {
+      display: inline-block;
+      padding-bottom: 16px;
+    }
+    .diff-side {
+      overflow-x: scroll;
+      width: 508px;
+      height: 700px;
+    }
+    .diff-side.diff-side-left{
+      overflow-y:hidden;
+    }
+    .diff-side table, td.diff-middle table {
+      height: 700px;
+    }
+    .diff-middle {
+      width: 114px;
+      vertical-align: top;
+      height: 700px;
+      overflow: hidden
+    }
+
+    .old_line, .new_line, .diff_line {
+      margin: 0px;
+      padding: 0px;
+      border: none;
+      background: #EEE;
+      color: #666;
+      padding: 0px 5px;
+      border-right: 1px solid #ccc;
+      text-align: right;
+      min-width: 35px;
+      max-width: 50px;
+      width: 35px;
+      @include user-select(none);
+      a {
+        float: left;
+        width: 35px;
+        font-weight: normal;
+        color: #666;
+        &:hover {
+          text-decoration: underline;
+        }
+      }
+      &.new {
+        background: #CFD;
+      }
+      &.old {
+        background: #FDD;
+      }
+    }
+    .diff_line {
+      padding: 0;
+    }
+    .line_holder {
+      &.old .old_line,
+      &.old .new_line {
+        background: #FCC;
+        border-color: #E7BABA;
+      }
+      &.new .old_line,
+      &.new .new_line {
+        background: #CFC;
+        border-color: #B9ECB9;
+      }
+    }
+    .line_content {
+      display: block;
+      white-space: pre;
+      height: 18px;
+      margin: 0px;
+      padding: 0px 0.5em;
+      border: none;
+      &.new {
+        background: #CFD;
+      }
+      &.old {
+        background: #FDD;
+      }
+      &.matched {
+        color: #ccc;
+        background: #fafafa;
+      }
+      &.parallel {
+        display: table-cell;
+      }
+    }
+  }
+  .image {
+    background: #ddd;
+    text-align: center;
+    padding: 30px;
+    .wrap{
+      display: inline-block;
+    }
+
+    .frame {
+      display: inline-block;
+      background-color: #fff;
+      line-height: 0;
+      img{
+        border: 1px solid #FFF;
+        background: image-url('trans_bg.gif');
+        max-width: 100%;
+      }
+      &.deleted {
+        border: 1px solid $deleted;
+      }
+
+      &.added {
+        border: 1px solid $added;
+      }
+    }
+    .image-info{
+      font-size: 12px;
+      margin: 5px 0 0 0;
+      color: grey;
+    }
+
+    .view.swipe{
+      position: relative;
+
+      .swipe-frame{
+        display: block;
+        margin: auto;
+        position: relative;
+      }
+      .swipe-wrap{
+        overflow: hidden;
+        border-left: 1px solid #999;
+        position: absolute;
+        display: block;
+        top: 13px;
+        right: 7px;
+      }
+      .frame{
+        top: 0;
+        right: 0;
+        position: absolute;
+        &.deleted{
+          margin: 0;
+          display: block;
+          top: 13px;
+          right: 7px;
+        }
+      }
+      .swipe-bar{
+        display: block;
+        height: 100%;
+        width: 15px;
+        z-index: 100;
+        position: absolute;
+        cursor: pointer;
+        &:hover{
+          .top-handle{
+            background-position: -15px 3px;
+          }
+          .bottom-handle{
+            background-position: -15px -11px;
+          }
+        };
+        .top-handle{
+          display: block;
+          height: 14px;
+          width: 15px;
+          position: absolute;
+          top: 0px;
+          background: image-url('swipemode_sprites.gif') 0 3px no-repeat;
+        }
+        .bottom-handle{
+          display: block;
+          height: 14px;
+          width: 15px;
+          position: absolute;
+          bottom: 0px;
+          background: image-url('swipemode_sprites.gif') 0 -11px no-repeat;
+        }
+      }
+    } //.view.swipe
+    .view.onion-skin{
+      .onion-skin-frame{
+        display: block;
+        margin: auto;
+        position: relative;
+      }
+      .frame.added, .frame.deleted {
+        position: absolute;
+        display: block;
+        top: 0px;
+        left: 0px;
+      }
+      .controls{
+        display: block;
+        height: 14px;
+        width: 300px;
+        z-index: 100;
+        position: absolute;
+        bottom: 0px;
+        left: 50%;
+        margin-left: -150px;
+
+        .drag-track{
+          display: block;
+          position: absolute;
+          left: 12px;
+          height: 10px;
+          width: 276px;
+          background: image-url('onion_skin_sprites.gif') -4px -20px repeat-x;
+        }
+
+        .dragger {
+          display: block;
+          position: absolute;
+          left: 0px;
+          top: 0px;
+          height: 14px;
+          width: 14px;
+          background: image-url('onion_skin_sprites.gif') 0px -34px repeat-x;
+          cursor: pointer;
+        }
+
+        .transparent {
+          display: block;
+          position: absolute;
+          top: 2px;
+          right: 0px;
+          height: 10px;
+          width: 10px;
+          background: image-url('onion_skin_sprites.gif') -2px 0px no-repeat;
+        }
+
+        .opaque {
+          display: block;
+          position: absolute;
+          top: 2px;
+          left: 0px;
+          height: 10px;
+          width: 10px;
+          background: image-url('onion_skin_sprites.gif') -2px -10px no-repeat;
+        }
+      }
+    } //.view.onion-skin
+  }
+  .view-modes{
+
+    padding: 10px;
+    text-align: center;
+
+    background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
+    background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
+    background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
+    background-image: -ms-linear-gradient(#eee 6.6%, #dfdfdf);
+    background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
+
+    ul, li{
+      list-style: none;
+      margin: 0;
+      padding: 0;
+      display: inline-block;
+    }
+
+    li{
+      color: grey;
+      border-left: 1px solid #c1c1c1;
+      padding: 0 12px 0 16px;
+      cursor: pointer;
+      &:first-child{
+        border-left: none;
+      }
+      &:hover{
+        text-decoration: underline;
+      }
+      &.active{
+        &:hover{
+          text-decoration: none;
+        }
+        cursor: default;
+        color: #333;
+      }
+      &.disabled{
+        display: none;
+      }
+    }
+  }
+}
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index d3462d6aaa7fd37f94ac18a07c2dc7fa07c81e44..22ee2f818240171d16f9e0c474d2b090c162b8c1 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -102,3 +102,8 @@
     }
   }
 }
+
+.merge-request-review-button {
+  float: left;
+  margin: 0 8px 15px 0;
+}
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 0792dbf041f35c1c511d2d4e2fd77e2be59d8151..9d2e4ddd19ba0a84b48e0cf97b93b4d0f138fbf8 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -2,7 +2,7 @@ require 'gitlab/satellite/satellite'
 
 class Projects::MergeRequestsController < Projects::ApplicationController
   before_filter :module_enabled
-  before_filter :merge_request, only: [:edit, :update, :show, :diffs, :automerge, :automerge_check, :ci_status]
+  before_filter :merge_request, only: [:edit, :update, :show, :diffs, :automerge, :automerge_check, :ci_status, :accept_without_merge, :reject, :mark_fixed]
   before_filter :closes_issues, only: [:edit, :update, :show, :diffs]
   before_filter :validates_merge_request, only: [:show, :diffs]
   before_filter :define_show_vars, only: [:show, :diffs]
@@ -26,8 +26,16 @@ class Projects::MergeRequestsController < Projects::ApplicationController
 
     @sort = params[:sort].humanize
     assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
+    assigned_group_id, created_group_id = params[:assigned_group_id], params[:created_group_id]
     @assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
     @milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
+    @user_groups = current_user.users_groups
+    @assigned_group = @user_groups.where(group_id: assigned_group_id).first.group if assigned_group_id.present?
+    @created_group = @user_groups.where(group_id: created_group_id).first.group if created_group_id.present?
+    # Merge request states, which will be available in the corresponding filter.
+    # We want to display all states, which displayed in the list MRs can have (i.e. everything what can be merged).
+    @available_states = MergeRequest::VALID_STATES_FOR_MERGE
+    @mr_state = params[:mr_state]
   end
 
   def show
@@ -137,6 +145,31 @@ class Projects::MergeRequestsController < Projects::ApplicationController
     end
   end
 
+  def change_review_status(appropriate_current_statuses, change_status_method, review_action)
+    return access_denied! unless allowed_to_review?
+
+    if appropriate_current_statuses.include?(@merge_request.state)
+      @merge_request.send(change_status_method)
+      @status = true
+    else
+      @status = false
+    end
+    @review_action = review_action
+    render "_review"
+  end
+
+  def accept_without_merge
+    change_review_status(MergeRequest::VALID_STATES_FOR_ACCEPT, :accept, 'accept (without merge)')
+  end
+
+  def reject
+    change_review_status(MergeRequest::VALID_STATES_FOR_REJECT, :reject, 'reject')
+  end
+
+  def mark_fixed
+    change_review_status(MergeRequest::VALID_STATES_FOR_MARK_FIXED, :mark_fixed, 'mark as fixed')
+  end
+
   def branch_from
     #This is always source
     @source_project = @merge_request.nil? ? @project : @merge_request.source_project
@@ -152,6 +185,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
     @target_project = selected_target_project
     @target_branches = @target_project.repository.branch_names
     @target_branches
+
+    respond_to do |format|
+      format.js
+    end
   end
 
   def ci_status
@@ -214,17 +251,35 @@ class Projects::MergeRequestsController < Projects::ApplicationController
     @commits = @merge_request.commits
 
     @allowed_to_merge = allowed_to_merge?
-    @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge
+    @show_merge_controls = MergeRequest::VALID_STATES_FOR_MERGE.include?(@merge_request.state) && @merge_request.opened? && @commits.any? && @allowed_to_merge
+
+    @allowed_to_review = allowed_to_review?
+    @show_accept_button = MergeRequest::VALID_STATES_FOR_ACCEPT.include?(@merge_request.state) && @allowed_to_review
+    @show_reject_button = MergeRequest::VALID_STATES_FOR_REJECT.include?(@merge_request.state) && @allowed_to_review
+    @show_mark_fixed_button = MergeRequest::VALID_STATES_FOR_MARK_FIXED.include?(@merge_request.state) && @allowed_to_review
+
+    @target_type = :merge_request
+    @target_id = @merge_request.id
+
+    @protected_source_branch = project.protected_branch?(@merge_request.source_branch)
   end
 
   def allowed_to_merge?
-    action = if project.protected_branch?(@merge_request.target_branch)
+    action = if @merge_request.assignee == current_user
+               :push_code
+             elsif project.protected_branch?(@merge_request.target_branch)
                :push_code_to_protected_branches
              else
                :push_code
              end
 
-    can?(current_user, action, @project)
+    can_push_code = can?(current_user, action, @project)
+    can_merge = can?(current_user, :merge_merge_request, @project)
+    return can_push_code && can_merge
+  end
+
+  def allowed_to_review?
+    can?(current_user, :review_merge_request, @project)
   end
 
   def invalid_mr
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 663369e45840443129ebab1d294be060043fe2a1..f8ec8e10fd1b5037a9c90cda82e1e5a343f34444 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -105,8 +105,80 @@ module CommitsHelper
     branches.sort.map { |branch| link_to(branch, project_tree_path(project, branch)) }.join(", ").html_safe
   end
 
-  def get_old_file(project, commit, diff)
-    project.repository.blob_at(commit.parent_id, diff.old_path) if commit.parent_id
+  def parallel_diff_lines(project, commit, diff, file)
+    old_file = project.repository.blob_at(commit.parent_id, diff.old_path) if commit.parent_id
+    deleted_lines = {}
+    added_lines = {}
+    each_diff_line(diff, 0) do |line, type, line_code, line_new, line_old|
+      if type == "old"
+        deleted_lines[line_old] = { line_code: line_code, type: type, line: line }
+      elsif type == "new"
+        added_lines[line_new]   = { line_code: line_code, type: type, line: line }
+      end
+    end
+    max_length = old_file ? old_file.sloc + added_lines.length : file.sloc
+
+    offset1 = 0
+    offset2 = 0
+    old_lines = []
+    new_lines = []
+
+    max_length.times do |line_index|
+      line_index1 = line_index - offset1
+      line_index2 = line_index - offset2
+      deleted_line = deleted_lines[line_index1 + 1]
+      added_line = added_lines[line_index2 + 1]
+      old_line = old_file.lines[line_index1] if old_file
+      new_line = file.lines[line_index2]
+
+      if deleted_line && added_line
+      elsif deleted_line
+        new_line = nil
+        offset2 += 1
+      elsif added_line
+        old_line = nil
+        offset1 += 1
+      end
+
+      old_lines[line_index] = DiffLine.new
+      new_lines[line_index] = DiffLine.new
+
+      # old
+      if line_index == 0 && diff.new_file
+        old_lines[line_index].type = :file_created
+        old_lines[line_index].content = 'File was created'
+      elsif deleted_line
+        old_lines[line_index].type = :deleted
+        old_lines[line_index].content = old_line
+        old_lines[line_index].num = line_index1 + 1
+        old_lines[line_index].code = deleted_line[:line_code]
+      elsif old_line
+        old_lines[line_index].type = :no_change
+        old_lines[line_index].content = old_line
+        old_lines[line_index].num = line_index1 + 1
+      else
+        old_lines[line_index].type = :added
+      end
+
+      # new
+      if line_index == 0 && diff.deleted_file
+        new_lines[line_index].type = :file_deleted
+        new_lines[line_index].content = "File was deleted"
+      elsif added_line
+        new_lines[line_index].type = :added
+        new_lines[line_index].num = line_index2 + 1
+        new_lines[line_index].content = new_line
+        new_lines[line_index].code = added_line[:line_code]
+      elsif new_line
+        new_lines[line_index].type = :no_change
+        new_lines[line_index].num = line_index2 + 1
+        new_lines[line_index].content = new_line
+      else
+        new_lines[line_index].type = :deleted
+      end
+    end
+
+    return old_lines, new_lines
   end
 
   protected
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 5e3f82fe9ceffdc29bc6fd96569a692f8d95cbdc..5ce8f814ee78d9f0eeb1c71fe8dc2b70a026c943 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -19,7 +19,7 @@ module MergeRequestsHelper
       target_project_id: target_project.id,
       source_branch: event.branch_name,
       target_branch: target_project.repository.root_ref,
-      title: event.branch_name.titleize
+      title: event.branch_name
     }
   end
 
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index a6a507360bdf060f7850310dab7ff2469b112aa1..32796a969029747c8bbd7a0a9054bb8bbeea2a0b 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -66,7 +66,11 @@ module ProjectsHelper
 
   def project_filter_path(options={})
     exist_opts = {
+      assignee_id: params[:assignee_id],
+      assigned_group_id: params[:assigned_group_id],
+      created_group_id: params[:created_group_id],
       state: params[:state],
+      mr_state: params[:mr_state],
       scope: params[:scope],
       label_name: params[:label_name],
       milestone_id: params[:milestone_id],
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 25b8bf755e2d6660709fd70d11f1e586f803e338..e839d509ddad4cab26865ba7cbe59d396ab1342a 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -2,28 +2,36 @@ module Emails
   module MergeRequests
     def new_merge_request_email(recipient_id, merge_request_id)
       @merge_request = MergeRequest.find(merge_request_id)
+      @author = User.find(@merge_request.author_id)
       @project = @merge_request.project
-      mail(to: recipient(recipient_id), subject: subject("New merge request ##{@merge_request.iid}", @merge_request.title))
+      mail(to: recipient(recipient_id), subject: subject("#{@author.name} created merge request !#{@merge_request.iid}", @merge_request.title))
     end
 
-    def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
+    def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id, assigned_by)
       @merge_request = MergeRequest.find(merge_request_id)
       @previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id
       @project = @merge_request.project
-      mail(to: recipient(recipient_id), subject: subject("Changed merge request ##{@merge_request.iid}", @merge_request.title))
+      mail(to: recipient(recipient_id), subject: subject("#{assigned_by.name} reassigned !#{@merge_request.iid} | #{@merge_request.title} to #{@merge_request.assignee.name}"))
     end
 
     def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
       @merge_request = MergeRequest.find(merge_request_id)
       @updated_by = User.find updated_by_user_id
       @project = @merge_request.project
-      mail(to: recipient(recipient_id), subject: subject("Closed merge request ##{@merge_request.iid}", @merge_request.title))
+      mail(to: recipient(recipient_id), subject: subject("#{@updated_by.name} closed merge request !#{@merge_request.iid}", @merge_request.title))
     end
 
-    def merged_merge_request_email(recipient_id, merge_request_id)
+    def reviewed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, action)
+      @merge_request = MergeRequest.find(merge_request_id)
+      @updated_by = User.find updated_by_user_id
+      @action = action
+      mail(to: recipient(recipient_id), subject: subject("#{@updated_by.name} #{action} !#{@merge_request.iid}", @merge_request.title))
+    end
+
+    def merged_merge_request_email(recipient_id, merge_request_id, merged_by)
       @merge_request = MergeRequest.find(merge_request_id)
       @project = @merge_request.project
-      mail(to: recipient(recipient_id), subject: subject("Accepted merge request ##{@merge_request.iid}", @merge_request.title))
+      mail(to: recipient(recipient_id), subject: subject("#{merged_by.name} merged !#{@merge_request.iid}", @merge_request.title))
     end
   end
 
diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb
index e967cf6dc739cb7f4257caf3bd456edb44bcaeaa..6630672bd2473a32f231ea08e9e8b4ac28583c1c 100644
--- a/app/mailers/emails/notes.rb
+++ b/app/mailers/emails/notes.rb
@@ -18,7 +18,7 @@ module Emails
       @note = Note.find(note_id)
       @merge_request = @note.noteable
       @project = @note.project
-      mail(to: recipient(recipient_id), subject: subject("Note for merge request ##{@merge_request.iid}"))
+      mail(to: recipient(recipient_id), subject: subject("#{@note.author_name} commented on ##{@merge_request.iid}", @merge_request.title))
     end
 
     def note_wall_email(recipient_id, note_id)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index cf925141f2d193b4cb4a1080f8f2d33fd8cdc843..65e5b00950f55026093785c68a346b3690b6e38c 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -61,6 +61,9 @@ class Ability
       if team.masters.include?(user)
         rules += project_master_rules
 
+      elsif team.developers_with_merge.include?(user)
+        rules += project_dev_with_merge_rules
+
       elsif team.developers.include?(user)
         rules += project_dev_rules
 
@@ -125,7 +128,15 @@ class Ability
       project_report_rules + [
         :write_merge_request,
         :write_wiki,
-        :push_code
+        :push_code,
+        :modify_merge_request,
+        :review_merge_request
+      ]
+    end
+
+    def project_dev_with_merge_rules
+      project_dev_rules + [
+        :merge_merge_request
       ]
     end
 
@@ -144,7 +155,7 @@ class Ability
         :push_code_to_protected_branches,
         :modify_issue,
         :modify_project_snippet,
-        :modify_merge_request,
+        :merge_merge_request,
         :admin_issue,
         :admin_milestone,
         :admin_project_snippet,
diff --git a/app/models/diff_line.rb b/app/models/diff_line.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ad37945874a69fd21511b0646f1344273e9a6b17
--- /dev/null
+++ b/app/models/diff_line.rb
@@ -0,0 +1,3 @@
+class DiffLine
+  attr_accessor :type, :content, :num, :code
+end
diff --git a/app/models/event.rb b/app/models/event.rb
index ddb863c1be24ab1ca0777f90ffd4e33b336f4662..40af22fda036378461a3ca214b5f2074005e51b9 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -29,6 +29,9 @@ class Event < ActiveRecord::Base
   MERGED    = 7
   JOINED    = 8 # User joined project
   LEFT      = 9 # User left project
+  ACCEPTED  = 101 # User accepted merge request
+  REJECTED  = 102 # User rejected merge request
+  FIXED     = 103 # User fixed merge request
 
   delegate :name, :email, to: :author, prefix: true, allow_nil: true
   delegate :title, to: :issue, prefix: true, allow_nil: true
@@ -141,6 +144,18 @@ class Event < ActiveRecord::Base
     action == LEFT
   end
 
+  def accepted?
+     action == ACCEPTED
+  end
+
+  def rejected?
+     action == REJECTED
+  end
+
+  def fixed?
+    action == FIXED
+  end
+
   def membership_changed?
     joined? || left?
   end
@@ -162,6 +177,12 @@ class Event < ActiveRecord::Base
       'joined'
     elsif left?
       'left'
+    elsif accepted?
+      'accepted (without merge)'
+    elsif rejected?
+      'rejected'
+    elsif fixed?
+      'fixed'
     else
       "opened"
     end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index da7aebd944f48f1de664ae3191d2da7494c67b44..5fce34cc5bdb1743686ed422345bb6a57d7a9dfd 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -41,17 +41,30 @@ class MergeRequest < ActiveRecord::Base
 
   state_machine :state, initial: :opened do
     event :close do
-      transition [:reopened, :opened] => :closed
+      transition [:reopened, :opened, :accepted, :rejected, :fixed] => :closed
     end
 
     event :merge do
-      transition [:reopened, :opened] => :merged
+      transition [:reopened, :opened, :accepted, :rejected, :fixed] => :merged
+    end
+
+    event :accept do
+      transition [:reopened, :opened, :fixed, :rejected] => :accepted
+    end
+
+    event :reject do
+      transition [:reopened, :opened, :fixed, :accepted] => :rejected
+    end
+
+    event :mark_fixed do
+      transition [:rejected] => :fixed
     end
 
     event :reopen do
       transition closed: :reopened
     end
 
+    # New (not reviewed merge request)
     state :opened
 
     state :reopened
@@ -59,6 +72,15 @@ class MergeRequest < ActiveRecord::Base
     state :closed
 
     state :merged
+
+    # Reviewed and without issues which should be fixed, but not merged yet
+    state :accepted
+
+    # Reviewed and containing some issues
+    state :rejected
+
+    # Fixed after review
+    state :fixed
   end
 
   state_machine :merge_status, initial: :unchecked do
@@ -92,7 +114,8 @@ class MergeRequest < ActiveRecord::Base
 
   scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.project_ids) }
   scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))", team_project_ids: team.project_ids, team_member_ids: team.member_ids) }
-  scope :opened, -> { with_state(:opened) }
+  # Hack: we want the review states ('accepted', 'rejected', 'fixed') to behave in the same way as the 'opened' one
+  scope :opened, -> { with_states(:opened, :accepted, :rejected, :fixed) }
   scope :closed, -> { with_state(:closed) }
   scope :merged, -> { with_state(:merged) }
   scope :by_branch, ->(branch_name) { where("(source_branch LIKE :branch) OR (target_branch LIKE :branch)", branch: branch_name) }
@@ -104,6 +127,16 @@ class MergeRequest < ActiveRecord::Base
   # both merged and closed mr's
   scope :closed, -> { with_states(:closed, :merged) }
 
+  VALID_STATES_FOR_MERGE = ["opened", "reopened", "accepted", "rejected", "fixed", "closed", "merged"]
+  VALID_STATES_FOR_ACCEPT = ["opened", "reopened", "rejected", "fixed"]
+  VALID_STATES_FOR_REJECT = ["opened", "reopened", "accepted", "fixed"]
+  VALID_STATES_FOR_MARK_FIXED = ["rejected"]
+
+  # Hack: we want the review states ('accepted', 'rejected', 'fixed') to behave in the same way as the 'opened' one
+  def opened?
+    return state == "opened" || accepted? || rejected? || fixed?
+  end
+
   def validate_branches
     if target_project==source_project && target_branch == source_branch
       errors.add :branch_conflict, "You can not use same project/branch for source and target"
@@ -328,6 +361,10 @@ class MergeRequest < ActiveRecord::Base
     message
   end
 
+  def project
+    target_project
+  end
+
   private
 
   def dump_commits(commits)
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 5630f280aea13841b6ecb6ca9c20a22152ba4038..956944a86e62c0c7eb671c0a04dede4107754d25 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -84,6 +84,10 @@ class ProjectTeam
     @developers ||= fetch_members(:developers)
   end
 
+  def developers_with_merge
+    @developers_with_merge ||= fetch_members(:developers_with_merge)
+  end
+
   def masters
     @masters ||= fetch_members(:masters)
   end
diff --git a/app/models/users_group.rb b/app/models/users_group.rb
index 181bf3222832b98d26f84938d95b335fa9c1e8bd..1a14100e43a916f68a89accd65f48bbca7dff0b1 100644
--- a/app/models/users_group.rb
+++ b/app/models/users_group.rb
@@ -27,6 +27,7 @@ class UsersGroup < ActiveRecord::Base
   scope :guests, -> { where(group_access: GUEST) }
   scope :reporters, -> { where(group_access: REPORTER) }
   scope :developers, -> { where(group_access: DEVELOPER) }
+  scope :developers_with_merge, -> { where(group_access: DEVELOPER_WITH_MERGE) }
   scope :masters,  -> { where(group_access: MASTER) }
   scope :owners,  -> { where(group_access: OWNER) }
 
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 6f147859a5cf538184b7dba91e7cc31944073136..8ac2eaab612c776732771866b1401bf56b9f630d 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -31,6 +31,7 @@ class UsersProject < ActiveRecord::Base
   scope :guests, -> { where(project_access: GUEST) }
   scope :reporters, -> { where(project_access: REPORTER) }
   scope :developers, -> { where(project_access: DEVELOPER) }
+  scope :developers_with_merge, -> { where(project_access: DEVELOPER_WITH_MERGE) }
   scope :masters,  -> { where(project_access: MASTER) }
 
   scope :in_project, ->(project) { where(project_id: project.id) }
diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb
index 0ac555fce7c640b57da32f3dbd90608cbf060cdc..2131c4da82580eda11c661485f3c3488772e3be7 100644
--- a/app/observers/merge_request_observer.rb
+++ b/app/observers/merge_request_observer.rb
@@ -19,7 +19,7 @@ class MergeRequestObserver < ActivityObserver
   end
 
   def after_merge(merge_request, transition)
-    notification.merge_mr(merge_request)
+    notification.merge_mr(merge_request, current_user)
     # Since MR can be merged via sidekiq
     # to prevent event duplication do this check
     return true if merge_request.merge_event
@@ -35,6 +35,21 @@ class MergeRequestObserver < ActivityObserver
     execute_hooks(merge_request)
   end
 
+  def after_accept(merge_request, transition)
+    notification.review_mr(merge_request, current_user, 'accepted (without merge)')
+    create_event(merge_request, Event::ACCEPTED)
+  end
+
+  def after_reject(merge_request, transition)
+    notification.review_mr(merge_request, current_user, 'rejected')
+    create_event(merge_request, Event::REJECTED)
+  end
+
+  def after_mark_fixed(merge_request, transition)
+    notification.review_mr(merge_request, current_user, 'fixed')
+    create_event(merge_request, Event::FIXED)
+  end
+
   def after_reopen(merge_request, transition)
     create_event(merge_request, Event::REOPENED)
     create_note(merge_request)
diff --git a/app/services/filtering_service.rb b/app/services/filtering_service.rb
index b339065890bc7c01f0863478afc59581655c8cd1..7ee61d7db94c611faeb31299eea8013a76987686 100644
--- a/app/services/filtering_service.rb
+++ b/app/services/filtering_service.rb
@@ -31,6 +31,9 @@ class FilteringService
     items = by_search(items)
     items = by_milestone(items)
     items = by_assignee(items)
+    items = by_assigned_group_id(items)
+    items = by_created_group_id(items)
+    items = by_mr_state(items)
     items = by_label(items)
     items = sort(items)
   end
@@ -113,6 +116,30 @@ class FilteringService
     items
   end
 
+  def by_assigned_group_id(items)
+    if params[:assigned_group_id].present?
+      items = items.joins(assignee: :users_groups).where(users_groups: {group_id: params[:assigned_group_id]})
+    end
+
+    items
+  end
+
+  def by_created_group_id(items)
+    if params[:created_group_id].present?
+      items = items.joins(author: :users_groups).where(users_groups: {group_id: params[:created_group_id]})
+    end
+
+    items
+  end
+
+  def by_mr_state(items)
+    if params[:mr_state].present?
+      items = items.where(state: params[:mr_state])
+    end
+
+    items
+  end
+
   def by_label(items)
     if params[:label_name].present?
       items = items.tagged_with(params[:label_name])
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index ebbb556b63cff322419d4d218bb9a90981eceba4..e0e7f13f6fff94050c3d39f0a52164aa7e356ffe 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -73,18 +73,28 @@ class NotificationService
     close_resource_email(merge_request, merge_request.target_project, current_user, 'closed_merge_request_email')
   end
 
+  # When we change a merge request's review state we should send next emails:
+  #
+  #  * merge_request author if his notification level is not Disabled
+  #  * merge_request assignee if his notification level is not Disabled
+  #  * project team members with notification level higher then Participating
+  #
+  def review_mr(merge_request, current_user, action)
+    review_mr_email(merge_request, merge_request.target_project, current_user, action)
+  end
+
   # When we merge a merge request we should send next emails:
   #
   #  * merge_request author if their notification level is not Disabled
   #  * merge_request assignee if their notification level is not Disabled
   #  * project team members with notification level higher then Participating
   #
-  def merge_mr(merge_request)
+  def merge_mr(merge_request, current_user)
     recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.target_project)
     recipients = recipients.concat(project_watchers(merge_request.target_project)).uniq
 
     recipients.each do |recipient|
-      mailer.merged_merge_request_email(recipient.id, merge_request.id)
+      mailer.merged_merge_request_email(recipient.id, merge_request.id, current_user)
     end
   end
 
@@ -227,6 +237,16 @@ class NotificationService
     end
   end
 
+  def review_mr_email(target, project, current_user, action)
+    recipients = reject_muted_users([target.author, target.assignee], project)
+    recipients = recipients.concat(project_watchers(project)).uniq
+    recipients.delete(current_user)
+
+    recipients.each do |recipient|
+      mailer.send('reviewed_merge_request_email', recipient.id, target.id, current_user.id, action)
+    end
+  end
+
   def close_resource_email(target, project, current_user, method)
     recipients = reject_muted_users([target.author, target.assignee], project)
     recipients = recipients.concat(project_watchers(project)).uniq
@@ -250,7 +270,7 @@ class NotificationService
     recipients.delete(current_user)
 
     recipients.each do |recipient|
-      mailer.send(method, recipient.id, target.id, target.assignee_id_was)
+      mailer.send(method, recipient.id, target.id, target.assignee_id_was, current_user)
     end
   end
 
diff --git a/app/views/help/permissions.html.haml b/app/views/help/permissions.html.haml
index 15e3bf3a135c755af28a4b9999fde3abe7a8a811..11a6521c1eee46e9f467c0fd8c2bc2d9aeea1348 100644
--- a/app/views/help/permissions.html.haml
+++ b/app/views/help/permissions.html.haml
@@ -13,6 +13,7 @@
         %th Guest
         %th Reporter
         %th Developer
+        %th Extended Developer
         %th Master
         %th Owner
     %tbody
@@ -172,6 +173,7 @@
         %th Guest
         %th Reporter
         %th Developer
+        %th Extended Developer
         %th Master
         %th Owner
     %tbody
diff --git a/app/views/notify/reviewed_merge_request_email.html.haml b/app/views/notify/reviewed_merge_request_email.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..681da7c49abf9a368745ea4637f271b5678bd04e
--- /dev/null
+++ b/app/views/notify/reviewed_merge_request_email.html.haml
@@ -0,0 +1,9 @@
+%p
+  = "Merge Request #{@merge_request.iid} was #{@action} by #{@updated_by.name}"
+%p
+  = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
+%p
+  != merge_path_description(@merge_request, '&rarr;')
+%p
+  Assignee: #{@merge_request.author_name} &rarr; #{@merge_request.assignee_name}
+
diff --git a/app/views/notify/reviewed_merge_request_email.text.haml b/app/views/notify/reviewed_merge_request_email.text.haml
new file mode 100644
index 0000000000000000000000000000000000000000..b3d1134a84c0caab20f70a951c6c5f5704b885a5
--- /dev/null
+++ b/app/views/notify/reviewed_merge_request_email.text.haml
@@ -0,0 +1,8 @@
+= "Merge Request #{@merge_request.iid} was #{@action} by #{@updated_by.name}"
+
+Merge Request Url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+
+= merge_path_description(@merge_request, 'to')
+
+Author: #{@merge_request.author_name}
+Assignee: #{@merge_request.assignee_name}
diff --git a/app/views/projects/commits/_parallel_view.html.haml b/app/views/projects/commits/_parallel_view.html.haml
index 3234e9da0ac88fa923ee22fb156ea49cdc5e56db..5b60ab80ba45dd8111f49b50225ebde0ce0c28f0 100644
--- a/app/views/projects/commits/_parallel_view.html.haml
+++ b/app/views/projects/commits/_parallel_view.html.haml
@@ -1,75 +1,55 @@
 / Side-by-side diff view
-- old_file = get_old_file(project, @commit, diff)
-- deleted_lines = {}
-- added_lines = {}
-- each_diff_line(diff, index) do |line, type, line_code, line_new, line_old, raw_line|
-  - if type == "old"
-    - deleted_lines[line_old] = { line_code: line_code, type: type, line: line }
-  - elsif type == "new"
-    - added_lines[line_new]   = { line_code: line_code, type: type, line: line }
-
-- max_length = old_file.sloc + added_lines.length if old_file
-- max_length ||= file.sloc
-- offset1 = 0
-- offset2 = 0
+- old_lines, new_lines = parallel_diff_lines(project, @commit, diff, file)
+- num_lines = old_lines.length
 
 %div.text-file-parallel
-  %table{ style: "table-layout: fixed;" }
-    - max_length.times do |line_index|
-      - line_index1 = line_index - offset1
-      - line_index2 = line_index - offset2
-      - deleted_line = deleted_lines[line_index1 + 1]
-      - added_line = added_lines[line_index2 + 1]
-      - old_line = old_file.lines[line_index1] if old_file
-      - new_line = file.lines[line_index2]
+  %div.diff-side.diff-side-left
+    %table
+      - old_lines.each do |line|
+
+        %tr.line_holder.parallel
+          - if line.type == :file_created
+            %td.line_content.parallel= "File was created"
+          - elsif line.type == :deleted
+            %td.line_content{class: "parallel noteable_line old #{line.code}", "line_code" => line.code }= line.content
+          - else line.type == :no_change
+            %td.line_content.parallel= line.content
+
+  %div.diff-middle
+    %table
+      - num_lines.times do |index|
+        %tr
+          - if old_lines[index].type == :deleted
+            %td.old_line.old= old_lines[index].num
+          - else
+            %td.old_line= old_lines[index].num
+
+          %td.diff_line=""
 
-      - if deleted_line && added_line
-      - elsif deleted_line
-        - new_line = nil
-        - offset2 += 1
-      - elsif added_line
-        - old_line = nil
-        - offset1 += 1
+          - if new_lines[index].type == :added
+            %td.new_line.new= new_lines[index].num
+          - else
+            %td.new_line= new_lines[index].num
 
-      %tr.line_holder.parallel
-        - if line_index == 0 && diff.new_file
-          %td.line_content.parallel= "File was created"
-          %td.old_line= ""
-        - elsif deleted_line
-          %td.line_content{class: "parallel noteable_line old #{deleted_line[:line_code]}", "line_code" => deleted_line[:line_code] }= old_line
-          %td.old_line.old
-            = line_index1 + 1
-            - if @comments_allowed
-              =# render "projects/notes/diff_note_link", line_code: deleted_line[:line_code]
-        - elsif old_line
-          %td.line_content.parallel= old_line
-          %td.old_line= line_index1 + 1
-        - else
-          %td.line_content.parallel= ""
-          %td.old_line= ""
+  %div.diff-side.diff-side-right
+    %table
+      - new_lines.each do |line|
 
-        %td.diff_line= ""
+        %tr.line_holder.parallel
+          - if line.type == :file_deleted
+            %td.line_content.parallel= "File was deleted"
+          - elsif line.type == :added
+            %td.line_content{class: "parallel noteable_line new #{line.code}", "line_code" => line.code }= line.content
+          - else line.type == :no_change
+            %td.line_content.parallel= line.content
 
-        - if diff.deleted_file && line_index == 0
-          %td.new_line= ""
-          %td.line_content.parallel= "File was deleted"
-        - elsif added_line
-          %td.new_line.new
-            = line_index2 + 1
-            - if @comments_allowed
-              =# render "projects/notes/diff_note_link", line_code: added_line[:line_code]
-          %td.line_content{class: "parallel noteable_line new #{added_line[:line_code]}", "line_code" => added_line[:line_code] }= new_line
-        - elsif new_line
-          %td.new_line= line_index2 + 1
-          %td.line_content.parallel= new_line
-        - else
-          %td.new_line= ""
-          %td.line_content.parallel= ""
+:javascript
+  $('.diff-side-right').on('scroll', function(){
+    $('.diff-side-left, .diff-middle').scrollTop($(this).scrollTop());
+    $('.diff-side-left').scrollLeft($(this).scrollLeft());
+  });
 
-      - if @reply_allowed
-        - comments1 = []
-        - comments2 = []
-        - comments1 = @line_notes.select { |n| n.line_code == deleted_line[:line_code] }.sort_by(&:created_at) if deleted_line
-        - comments2 = @line_notes.select { |n| n.line_code == added_line[:line_code] }.sort_by(&:created_at) if added_line
-        - unless comments1.empty? && comments2.empty?
-          = render "projects/notes/diff_notes_with_reply_parallel", notes1: comments1, notes2: comments2, line1: deleted_line, line2: added_line
\ No newline at end of file
+  $('.diff-side-left').on('scroll', function(){
+    $('.diff-side-right, .diff-middle').scrollTop($(this).scrollTop()); // might never be relevant
+    $('.diff-side-right').scrollLeft($(this).scrollLeft());
+  });
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index ff763bca3070609fb4b2ab089b341b9da504a375..9863f1a12633e90e2f84f73869a6472a8384e2fc 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -2,6 +2,7 @@
   .merge-request-title
     %span.light= "##{merge_request.iid}"
     = link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.target_project, merge_request), class: "row_title"
+    %span.light= "(#{merge_request.state})"
     - if merge_request.merged?
       %small.pull-right
         %i.icon-ok
diff --git a/app/views/projects/merge_requests/_review.js.haml b/app/views/projects/merge_requests/_review.js.haml
new file mode 100644
index 0000000000000000000000000000000000000000..30c05d44ed37da99e7c4849e098a14e5fc1c271e
--- /dev/null
+++ b/app/views/projects/merge_requests/_review.js.haml
@@ -0,0 +1,7 @@
+-if @status
+  :plain
+    location.reload(true);
+-else
+  :plain
+    alert("Failed to #{@review_action} the merge request!");
+
diff --git a/app/views/projects/merge_requests/branch_from.js.haml b/app/views/projects/merge_requests/branch_from.js.haml
index ec4d7f2121be7ac2211f6fbe3773e055e765ea3c..7079eb50f8eaaf839bacf67a5f579e096427229e 100644
--- a/app/views/projects/merge_requests/branch_from.js.haml
+++ b/app/views/projects/merge_requests/branch_from.js.haml
@@ -3,5 +3,5 @@
   var mrTitle = $('#merge_request_title');
 
   if(mrTitle.val().length == 0) {
-    mrTitle.val("#{params[:ref].titleize}");
+    mrTitle.val("#{params[:ref]}");
   }
diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml
index a525a49015f7269b19c47b2cba21bae6f4fde9df..60582ec51b5cdd7078ec7f6e537e3b81dcdc1fca 100644
--- a/app/views/projects/merge_requests/index.html.haml
+++ b/app/views/projects/merge_requests/index.html.haml
@@ -37,6 +37,44 @@
                     = image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
                     = user.name
 
+          .dropdown.inline.prepend-left-10
+            %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
+              %i.icon-group
+              %span.light assigned to group:
+              - if @assigned_group.present?
+                %strong= @assigned_group.name
+              - else
+                Any
+              %b.caret
+            %ul.dropdown-menu
+              %li
+                = link_to project_filter_path(assigned_group_id: nil) do
+                  Any
+              - @user_groups.each do |user_group|
+                - group = user_group.group
+                %li
+                  = link_to project_filter_path(assigned_group_id: group.id) do
+                    = group.name
+
+          .dropdown.inline.prepend-left-10
+            %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
+              %i.icon-group
+              %span.light created by group:
+              - if @created_group.present?
+                %strong= @created_group.name
+              - else
+                Any
+              %b.caret
+            %ul.dropdown-menu
+              %li
+                = link_to project_filter_path(created_group_id: nil) do
+                  Any
+              - @user_groups.each do |user_group|
+                - group = user_group.group
+                %li
+                  = link_to project_filter_path(created_group_id: group.id) do
+                    = group.name
+
           .dropdown.inline.prepend-left-10
             %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
               %i.icon-time
@@ -60,8 +98,24 @@
                     %strong= milestone.title
                     %small.light= milestone.expires_at
 
-          .pull-right
-            = render 'shared/sort_dropdown'
+          .dropdown.inline.prepend-left-10
+            %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
+              %span.light state:
+              - if @mr_state.present?
+                %strong= @mr_state.capitalize
+              - else
+                Any
+              %b.caret
+            %ul.dropdown-menu
+              %li
+                = link_to project_filter_path(mr_state: nil) do
+                  Any
+              - @available_states.each do |mr_state|
+                %li
+                  = link_to project_filter_path(mr_state: mr_state) do
+                    = mr_state.capitalize
+
+          = render 'shared/sort_dropdown'
 
       %ul.well-list.mr-list
         = render @merge_requests
diff --git a/app/views/projects/merge_requests/show/_mr_accept.html.haml b/app/views/projects/merge_requests/show/_mr_accept.html.haml
index 352d843f49fb0082ec434cec5d27d908e4a606d7..859bb891e875325bc962b3300914934e08b14376 100644
--- a/app/views/projects/merge_requests/show/_mr_accept.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_accept.html.haml
@@ -31,11 +31,13 @@
         .accept-group
           .pull-left
             = f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request"
-          - unless @merge_request.disallow_source_branch_removal?
-            .remove_branch_holder.pull-left
-              = label_tag :should_remove_source_branch, class: "checkbox" do
-                = check_box_tag :should_remove_source_branch
-                Remove source-branch
+          - unless @protected_source_branch
+            - unless @merge_request.disallow_source_branch_removal?
+              .remove_branch_holder.pull-left
+                = label_tag :should_remove_source_branch, class: "checkbox" do
+                  = check_box_tag :should_remove_source_branch
+                  Remove source-branch
+          .clearfix
 
 
   .automerge_widget.no_satellite.hide
@@ -67,3 +69,18 @@
       %i.icon-refresh.icon-spin
       &nbsp;
       Merge is in progress. Please wait. Page will be automatically reloaded. &nbsp;
+
+- if @allowed_to_review
+  - if @show_accept_button
+    %span.merge-request-review-button
+      = form_for [:accept_without_merge, @project, @merge_request], remote: true, method: :get do |f|
+        = f.submit "Accept Without Merge", class: "btn btn-success accept_without_merge"
+  - if @show_reject_button
+    %span.merge-request-review-button
+      = form_for [:reject, @project, @merge_request], remote: true, method: :get do |f|
+        = f.submit "Reject", class: "btn btn-danger reject"
+  - if @show_mark_fixed_button
+    %span.merge-request-review-button
+      = form_for [:mark_fixed, @project, @merge_request], remote: true, method: :get do |f|
+        = f.submit "Mark as fixed", class: "btn btn-success mark_fixed"
+  .clearfix
diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml
index 08a3fdf869a6b742991034cb58143efb6d718082..2a04b87241f7e27c9a76fb394964185193d4ab1f 100644
--- a/app/views/projects/merge_requests/show/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_title.html.haml
@@ -1,5 +1,5 @@
 %h3.page-title
-  = "Merge Request ##{@merge_request.iid}"
+  = "Merge Request ##{@merge_request.iid} (#{@merge_request.state})"
   %small
     created #{time_ago_with_tooltip(@merge_request.created_at)}
 
diff --git a/app/views/projects/merge_requests/update_branches.js.haml b/app/views/projects/merge_requests/update_branches.js.haml
index 6a21551e811cfae63db3ed8b536f0d28b7b426de..ca21b3bc0deb365c4db2f3ecc72576c80cd5e4e4 100644
--- a/app/views/projects/merge_requests/update_branches.js.haml
+++ b/app/views/projects/merge_requests/update_branches.js.haml
@@ -1,5 +1,9 @@
 :plain
   $(".target_branch").html("#{escape_javascript(options_for_select(@target_branches))}");
-  $(".target_branch").trigger("select2:updated");
+
+  $('select.target_branch').select2({
+    width: 'resolve',
+    dropdownAutoWidth: true
+  });
+
   $(".mr_target_commit").html("");
-  $(".target_branch").trigger("change");
diff --git a/config/routes.rb b/config/routes.rb
index 315c339016b6c08b8f00496613a70d108ec68751..3fabb05b4cfde10a56471b24e0fbfcc155512ed5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -267,6 +267,9 @@ Gitlab::Application.routes.draw do
           get :automerge
           get :automerge_check
           get :ci_status
+          get :accept_without_merge
+          get :reject
+          get :mark_fixed
         end
 
         collection do
diff --git a/db/migrate/20131022131722_add_accepted_state_to_merge_request.rb b/db/migrate/20131022131722_add_accepted_state_to_merge_request.rb
new file mode 100644
index 0000000000000000000000000000000000000000..401ea7fc61b73f74aa5464ca00f8b75081155910
--- /dev/null
+++ b/db/migrate/20131022131722_add_accepted_state_to_merge_request.rb
@@ -0,0 +1,7 @@
+class AddAcceptedStateToMergeRequest < ActiveRecord::Migration
+  # We don't need the forward ("up") data migration
+  def down
+    # Return all 'accepted' MR's back to the 'opened' state
+    MergeRequest.where(state: :accepted).update_all(state: :opened)
+  end
+end
diff --git a/db/migrate/20131022131759_add_accepted_event.rb b/db/migrate/20131022131759_add_accepted_event.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2e463d0535dc989d42dcb831b80f0aa87c6262c4
--- /dev/null
+++ b/db/migrate/20131022131759_add_accepted_event.rb
@@ -0,0 +1,8 @@
+class AddAcceptedEvent < ActiveRecord::Migration
+  # We don't need the forward ("up") data migration
+  def down
+    # Remove all 'ACCEPTED' events
+    # 101 == Event::ACCEPTED, but I'm not sure whether that constant is supposed to be available when db:rollback is executed
+    Event.where(action: 101).delete_all
+  end
+end
diff --git a/db/migrate/20131029195936_add_rejected_and_fixed_states_to_merge_request.rb b/db/migrate/20131029195936_add_rejected_and_fixed_states_to_merge_request.rb
new file mode 100644
index 0000000000000000000000000000000000000000..80bff7d763765983f25d8e0766a1c7f352bb9860
--- /dev/null
+++ b/db/migrate/20131029195936_add_rejected_and_fixed_states_to_merge_request.rb
@@ -0,0 +1,7 @@
+class AddRejectedAndFixedStatesToMergeRequest < ActiveRecord::Migration
+  # We don't need the forward ("up") data migration
+  def down
+    # Return all rejected and fixed MR's back to the 'opened' state
+    MergeRequest.where(state: [:rejected, :fixed]).update_all(state: :opened)
+  end
+end
diff --git a/db/migrate/20131029200011_add_rejected_and_fixed_events.rb b/db/migrate/20131029200011_add_rejected_and_fixed_events.rb
new file mode 100644
index 0000000000000000000000000000000000000000..512e3e3f95c17029e2428a9f5e2f976b640ff4fe
--- /dev/null
+++ b/db/migrate/20131029200011_add_rejected_and_fixed_events.rb
@@ -0,0 +1,9 @@
+class AddRejectedAndFixedEvents < ActiveRecord::Migration
+  # We don't need the forward ("up") data migration
+  def down
+    # Remove all 'REJECTED' and 'FIXED' events
+    # 102 == Event::REJECTED
+    # 103 == Event::FIXED
+    Event.where(action: [102, 103]).delete_all
+  end
+end
diff --git a/db/migrate/20131101150042_update_reviewed_merge_requests.rb b/db/migrate/20131101150042_update_reviewed_merge_requests.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1bf00666621c740a2715e7594899b8e70167df7b
--- /dev/null
+++ b/db/migrate/20131101150042_update_reviewed_merge_requests.rb
@@ -0,0 +1,8 @@
+class UpdateReviewedMergeRequests < ActiveRecord::Migration
+  def up
+    # Update all merge requests in the review states (:accepted, :rejected, :fixed)
+    # This is normally done in Project.update_merge_requests(oldrev, newrev, ref, user) via a push hook,
+    # but only opened MRs were updated before, so we need to update the reviewed ones now
+    MergeRequest.where(state: [:accepted, :rejected, :fixed]).each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
+  end
+end
diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb
index 87f9cfab608ee17c4d659b0385b338654df6b74e..f22d33a39c984c6b07f467753d031168ae80cf97 100644
--- a/lib/gitlab/access.rb
+++ b/lib/gitlab/access.rb
@@ -5,11 +5,12 @@
 #
 module Gitlab
   module Access
-    GUEST     = 10
-    REPORTER  = 20
-    DEVELOPER = 30
-    MASTER    = 40
-    OWNER     = 50
+    GUEST                = 10
+    REPORTER             = 20
+    DEVELOPER            = 30
+    DEVELOPER_WITH_MERGE = 31
+    MASTER               = 40
+    OWNER                = 50
 
     class << self
       def values
@@ -21,6 +22,7 @@ module Gitlab
           "Guest"     => GUEST,
           "Reporter"  => REPORTER,
           "Developer" => DEVELOPER,
+          "Developer with merge" => DEVELOPER_WITH_MERGE,
           "Master"    => MASTER,
         }
       end
@@ -36,6 +38,7 @@ module Gitlab
           guest:     GUEST,
           reporter:  REPORTER,
           developer: DEVELOPER,
+          developer_with_merge: DEVELOPER_WITH_MERGE,
           master:    MASTER,
         }
       end
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index d1d959e152e101d321c763e734b1997cf595c4b4..cc39bc07cc7295d3e4813103c4d850405fed653b 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -1,6 +1,6 @@
 # GITLAB
 # Maintainer: @randx
-# App Version: 5.0
+# App Version: 6.1
 
 upstream gitlab {
   server unix:/home/git/gitlab/tmp/sockets/gitlab.socket;
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index b1e5348681686452639f0bb1e9a3d9947631872d..7253af094a2cf6b32ee77b4bb597fd11ac21b92d 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -192,9 +192,10 @@ describe Notify do
         end
 
         describe 'that are reassigned' do
+          let(:current_user) { create(:user, email: "current@email.com") }
           before(:each) { merge_request.stub(:assignee_id_was).and_return(previous_assignee.id) }
 
-          subject { Notify.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id) }
+          subject { Notify.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id, current_user) }
 
           it_behaves_like 'a multiple recipients email'