diff --git a/CHANGELOG b/CHANGELOG
index 3e4a10bb5a3f397600ebc265cd0fca07de43bf4a..02cbd9bb29598f2a12feb35be806bc70201582c0 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -25,6 +25,7 @@ v 8.10.0 (unreleased)
   - Updated layout for Projects, Groups, Users on Admin area !4424
   - Fix changing issue state columns in milestone view
   - Add notification settings dropdown for groups
+  - Render inline diffs for multiple changed lines following eachother
   - Wildcards for protected branches. !4665
   - Allow importing from Github using Personal Access Tokens. (Eric K Idema)
   - API: Todos !3188 (Robert Schilling)
diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb
index 789c14518b003260f302c86ac14928ec69c52cb2..72d9abeefcc2a1bae63028008bac0c6e079840ff 100644
--- a/lib/gitlab/diff/inline_diff.rb
+++ b/lib/gitlab/diff/inline_diff.rb
@@ -1,16 +1,30 @@
 module Gitlab
   module Diff
     class InlineDiff
+      # Regex to find a run of deleted lines followed by the same number of added lines
+      REGEX = %r{
+        # Runs start at the beginning of the string (the first line) or after a space (for an unchanged line)
+        (?:\A| )
+
+        # This matches a number of `-`s followed by the same number of `+`s through recursion
+        (?<del_ins>
+          -
+          \g<del_ins>?
+          \+
+        )
+
+        # Runs end at the end of the string (the last line) or before a space (for an unchanged line)
+        (?= |\z)
+      }x.freeze
+
       attr_accessor :old_line, :new_line, :offset
 
       def self.for_lines(lines)
-        local_edit_indexes = self.find_local_edits(lines)
+        changed_line_pairs = self.find_changed_line_pairs(lines)
 
         inline_diffs = []
 
-        local_edit_indexes.each do |index|
-          old_index = index
-          new_index = index + 1
+        changed_line_pairs.each do |old_index, new_index|
           old_line = lines[old_index]
           new_line = lines[new_index]
 
@@ -51,18 +65,28 @@ def inline_diffs
 
       private
 
-      def self.find_local_edits(lines)
-        line_prefixes = lines.map { |line| line.match(/\A([+-])/) ? $1 : ' ' }
-        joined_line_prefixes = " #{line_prefixes.join} "
-
-        offset = 0
-        local_edit_indexes = []
-        while index = joined_line_prefixes.index(" -+ ", offset)
-          local_edit_indexes << index
-          offset = index + 1
+      # Finds pairs of old/new line pairs that represent the same line that changed
+      def self.find_changed_line_pairs(lines)
+        # Prefixes of all diff lines, indicating their types
+        # For example: `" - +  -+  ---+++ --+  -++"`
+        line_prefixes = lines.each_with_object("") { |line, s| s << line[0] }.gsub(/[^ +-]/, ' ')
+
+        changed_line_pairs = []
+        line_prefixes.scan(REGEX) do
+          # For `"---+++"`, `begin_index == 0`, `end_index == 6`
+          begin_index, end_index = Regexp.last_match.offset(:del_ins)
+
+          # For `"---+++"`, `changed_line_count == 3`
+          changed_line_count = (end_index - begin_index) / 2
+
+          halfway_index = begin_index + changed_line_count
+          (begin_index...halfway_index).each do |i|
+            # For `"---+++"`, index 1 maps to 1 + 3 = 4
+            changed_line_pairs << [i, i + changed_line_count]
+          end
         end
 
-        local_edit_indexes
+        changed_line_pairs
       end
 
       def longest_common_prefix(a, b)
diff --git a/spec/lib/gitlab/diff/inline_diff_spec.rb b/spec/lib/gitlab/diff/inline_diff_spec.rb
index 95a993d26cf70be4c9be3f01a688cb7278b75e5a..8ca3f73509e471c8be4402df601cd6f9c7f61f3f 100644
--- a/spec/lib/gitlab/diff/inline_diff_spec.rb
+++ b/spec/lib/gitlab/diff/inline_diff_spec.rb
@@ -3,14 +3,19 @@
 describe Gitlab::Diff::InlineDiff, lib: true do
   describe '.for_lines' do
     let(:diff) do
-      <<eos
- class Test
--  def initialize(test = true)
-+  def initialize(test = false)
-     @test = test
-   end
- end
-eos
+      <<-EOF.strip_heredoc
+         class Test
+        -  def initialize(test = true)
+        +  def initialize(test = false)
+             @test = test
+        -    if true
+        -      @foo = "bar"
+        +    unless false
+        +      @foo = "baz"
+             end
+           end
+         end
+      EOF
     end
 
     let(:subject) { described_class.for_lines(diff.lines) }
@@ -20,8 +25,11 @@ class Test
       expect(subject[1]).to eq([25..27])
       expect(subject[2]).to eq([25..28])
       expect(subject[3]).to be_nil
-      expect(subject[4]).to be_nil
-      expect(subject[5]).to be_nil
+      expect(subject[4]).to eq([5..10])
+      expect(subject[5]).to eq([17..17])
+      expect(subject[6]).to eq([5..15])
+      expect(subject[7]).to eq([17..17])
+      expect(subject[8]).to be_nil
     end
   end