diff --git a/Gemfile b/Gemfile
index 2be46e99c6f594888348f883c1c63ca8650c75b2..9efb362e494eaa8b443418e31f63187cd9e06087 100644
--- a/Gemfile
+++ b/Gemfile
@@ -367,6 +367,6 @@ gem 'vmstat', '~> 2.3.0'
 gem 'sys-filesystem', '~> 1.1.6'
 
 # Gitaly GRPC client
-gem 'gitaly', '~> 0.6.0'
+gem 'gitaly', '~> 0.7.0'
 
 gem 'toml-rb', '~> 0.3.15', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 6c52f1d70d91b5adbebf2a1a9d87cc86524e4896..873cd8781ef0c4ec5c34f78696f10185ab646acd 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -265,7 +265,7 @@ GEM
       po_to_json (>= 1.0.0)
       rails (>= 3.2.0)
     gherkin-ruby (0.3.2)
-    gitaly (0.6.0)
+    gitaly (0.7.0)
       google-protobuf (~> 3.1)
       grpc (~> 1.0)
     github-linguist (4.7.6)
@@ -924,7 +924,7 @@ DEPENDENCIES
   gettext (~> 3.2.2)
   gettext_i18n_rails (~> 1.8.0)
   gettext_i18n_rails_js (~> 1.2.0)
-  gitaly (~> 0.6.0)
+  gitaly (~> 0.7.0)
   github-linguist (~> 4.7.0)
   gitlab-flowdock-git-hook (~> 1.0.1)
   gitlab-markup (~> 1.5.1)
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 8d54ce6eb2540bc8879ff1184005791ce25925d0..dbc0a22829eb217c6f921acb6ba17c0e2dd82f66 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -327,13 +327,21 @@ class Commit
 
   def raw_diffs(*args)
     if Gitlab::GitalyClient.feature_enabled?(:commit_raw_diffs)
-      Gitlab::GitalyClient::Commit.diff_from_parent(self, *args)
+      Gitlab::GitalyClient::Commit.new(project.repository).diff_from_parent(self, *args)
     else
       raw.diffs(*args)
     end
   end
 
-  delegate :deltas, to: :raw, prefix: :raw
+  def raw_deltas
+    @deltas ||= Gitlab::GitalyClient.migrate(:commit_deltas) do |is_enabled|
+      if is_enabled
+        Gitlab::GitalyClient::Commit.new(project.repository).commit_deltas(self)
+      else
+        raw.deltas
+      end
+    end
+  end
 
   def diffs(diff_options = nil)
     Gitlab::Diff::FileCollection::Commit.new(self, diff_options: diff_options)
diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb
index 019be15135309bdb434bc9085de707ca559ae2f9..31d1b66b4f726e1d52b0ae5b42096fc407e20976 100644
--- a/lib/gitlab/git/diff.rb
+++ b/lib/gitlab/git/diff.rb
@@ -183,6 +183,8 @@ module Gitlab
         when Gitaly::CommitDiffResponse
           init_from_gitaly(raw_diff)
           prune_diff_if_eligible(collapse)
+        when Gitaly::CommitDelta
+          init_from_gitaly(raw_diff)
         when nil
           raise "Nil as raw diff passed"
         else
@@ -278,15 +280,15 @@ module Gitlab
         end
       end
 
-      def init_from_gitaly(diff_msg)
-        @diff = diff_msg.raw_chunks.join
-        @new_path = encode!(diff_msg.to_path.dup)
-        @old_path = encode!(diff_msg.from_path.dup)
-        @a_mode = diff_msg.old_mode.to_s(8)
-        @b_mode = diff_msg.new_mode.to_s(8)
-        @new_file = diff_msg.from_id == BLANK_SHA
-        @renamed_file = diff_msg.from_path != diff_msg.to_path
-        @deleted_file = diff_msg.to_id == BLANK_SHA
+      def init_from_gitaly(msg)
+        @diff = msg.raw_chunks.join if msg.respond_to?(:raw_chunks)
+        @new_path = encode!(msg.to_path.dup)
+        @old_path = encode!(msg.from_path.dup)
+        @a_mode = msg.old_mode.to_s(8)
+        @b_mode = msg.new_mode.to_s(8)
+        @new_file = msg.from_id == BLANK_SHA
+        @renamed_file = msg.from_path != msg.to_path
+        @deleted_file = msg.to_id == BLANK_SHA
       end
 
       def prune_diff_if_eligible(collapse = false)
diff --git a/lib/gitlab/gitaly_client/commit.rb b/lib/gitlab/gitaly_client/commit.rb
index 8e9323b05e106ae8969b7e2b4a89b074f5013b89..15c57420fb248d34a5eafb325d938faee24b706f 100644
--- a/lib/gitlab/gitaly_client/commit.rb
+++ b/lib/gitlab/gitaly_client/commit.rb
@@ -5,41 +5,55 @@ module Gitlab
       # See http://stackoverflow.com/a/40884093/1856239 and https://github.com/git/git/blob/3ad8b5bf26362ac67c9020bf8c30eee54a84f56d/cache.h#L1011-L1012
       EMPTY_TREE_ID = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'.freeze
 
-      attr_accessor :stub
-
       def initialize(repository)
         @gitaly_repo = repository.gitaly_repository
-        @stub = Gitaly::Commit::Stub.new(nil, nil, channel_override: repository.gitaly_channel)
+        @repository = repository
       end
 
       def is_ancestor(ancestor_id, child_id)
+        stub = Gitaly::Commit::Stub.new(nil, nil, channel_override: @repository.gitaly_channel)
         request = Gitaly::CommitIsAncestorRequest.new(
           repository: @gitaly_repo,
           ancestor_id: ancestor_id,
           child_id: child_id
         )
 
-        @stub.commit_is_ancestor(request).value
+        stub.commit_is_ancestor(request).value
+      end
+
+      def diff_from_parent(commit, options = {})
+        request_params = commit_diff_request_params(commit, options)
+        request_params[:ignore_whitespace_change] = options.fetch(:ignore_whitespace_change, false)
+
+        response = diff_service_stub.commit_diff(Gitaly::CommitDiffRequest.new(request_params))
+        Gitlab::Git::DiffCollection.new(response, options)
       end
 
-      class << self
-        def diff_from_parent(commit, options = {})
-          repository = commit.project.repository
-          gitaly_repo = repository.gitaly_repository
-          stub = Gitaly::Diff::Stub.new(nil, nil, channel_override: repository.gitaly_channel)
-          parent = commit.parents[0]
-          parent_id = parent ? parent.id : EMPTY_TREE_ID
-          request = Gitaly::CommitDiffRequest.new(
-            repository: gitaly_repo,
-            left_commit_id: parent_id,
-            right_commit_id: commit.id,
-            ignore_whitespace_change: options.fetch(:ignore_whitespace_change, false),
-            paths: options.fetch(:paths, [])
-          )
-
-          Gitlab::Git::DiffCollection.new(stub.commit_diff(request), options)
+      def commit_deltas(commit)
+        request_params = commit_diff_request_params(commit)
+
+        response = diff_service_stub.commit_delta(Gitaly::CommitDeltaRequest.new(request_params))
+        response.flat_map do |msg|
+          msg.deltas.map { |d| Gitlab::Git::Diff.new(d) }
         end
       end
+
+      private
+
+      def commit_diff_request_params(commit, options = {})
+        parent_id = commit.parents[0]&.id || EMPTY_TREE_ID
+
+        {
+          repository: @gitaly_repo,
+          left_commit_id: parent_id,
+          right_commit_id: commit.id,
+          paths: options.fetch(:paths, [])
+        }
+      end
+
+      def diff_service_stub
+        Gitaly::Diff::Stub.new(nil, nil, channel_override: @repository.gitaly_channel)
+      end
     end
   end
 end
diff --git a/spec/lib/gitlab/gitaly_client/commit_spec.rb b/spec/lib/gitlab/gitaly_client/commit_spec.rb
index 08c072caf8c836be6ee1f1191676b9c5c8d6248e..cf1bc74779e170c8ff1bf7252efcb250042d2399 100644
--- a/spec/lib/gitlab/gitaly_client/commit_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_spec.rb
@@ -1,12 +1,13 @@
 require 'spec_helper'
 
 describe Gitlab::GitalyClient::Commit do
-  describe '.diff_from_parent' do
-    let(:diff_stub) { double('Gitaly::Diff::Stub') }
-    let(:project) { create(:project, :repository) }
-    let(:repository_message) { project.repository.gitaly_repository }
-    let(:commit) { project.commit('913c66a37b4a45b9769037c55c2d238bd0942d2e') }
+  let(:diff_stub) { double('Gitaly::Diff::Stub') }
+  let(:project) { create(:project, :repository) }
+  let(:repository) { project.repository }
+  let(:repository_message) { repository.gitaly_repository }
+  let(:commit) { project.commit('913c66a37b4a45b9769037c55c2d238bd0942d2e') }
 
+  describe '#diff_from_parent' do
     context 'when a commit has a parent' do
       it 'sends an RPC request with the parent ID as left commit' do
         request = Gitaly::CommitDiffRequest.new(
@@ -17,7 +18,7 @@ describe Gitlab::GitalyClient::Commit do
 
         expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_diff).with(request)
 
-        described_class.diff_from_parent(commit)
+        described_class.new(repository).diff_from_parent(commit)
       end
     end
 
@@ -32,12 +33,12 @@ describe Gitlab::GitalyClient::Commit do
 
         expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_diff).with(request)
 
-        described_class.diff_from_parent(initial_commit)
+        described_class.new(repository).diff_from_parent(initial_commit)
       end
     end
 
     it 'returns a Gitlab::Git::DiffCollection' do
-      ret = described_class.diff_from_parent(commit)
+      ret = described_class.new(repository).diff_from_parent(commit)
 
       expect(ret).to be_kind_of(Gitlab::Git::DiffCollection)
     end
@@ -47,7 +48,38 @@ describe Gitlab::GitalyClient::Commit do
 
       expect(Gitlab::Git::DiffCollection).to receive(:new).with(kind_of(Enumerable), options)
 
-      described_class.diff_from_parent(commit, options)
+      described_class.new(repository).diff_from_parent(commit, options)
+    end
+  end
+
+  describe '#commit_deltas' do
+    context 'when a commit has a parent' do
+      it 'sends an RPC request with the parent ID as left commit' do
+        request = Gitaly::CommitDeltaRequest.new(
+          repository: repository_message,
+          left_commit_id: 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
+          right_commit_id: commit.id
+        )
+
+        expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_delta).with(request).and_return([])
+
+        described_class.new(repository).commit_deltas(commit)
+      end
+    end
+
+    context 'when a commit does not have a parent' do
+      it 'sends an RPC request with empty tree ref as left commit' do
+        initial_commit = project.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863')
+        request        = Gitaly::CommitDeltaRequest.new(
+          repository: repository_message,
+          left_commit_id: '4b825dc642cb6eb9a060e54bf8d69288fbee4904',
+          right_commit_id: initial_commit.id
+        )
+
+        expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_delta).with(request).and_return([])
+
+        described_class.new(repository).commit_deltas(initial_commit)
+      end
     end
   end
 end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 131fea8be430b1337733c13609de96662c77e679..72f83d6322476c4bbcfec288843c3d7db9a189ac 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -388,19 +388,4 @@ eos
       expect(described_class.valid_hash?('a' * 41)).to be false
     end
   end
-
-  describe '#raw_diffs' do
-    context 'Gitaly commit_raw_diffs feature enabled' do
-      before do
-        allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(:commit_raw_diffs).and_return(true)
-      end
-
-      it 'fetches diffs from Gitaly server' do
-        expect(Gitlab::GitalyClient::Commit).to receive(:diff_from_parent).
-          with(commit)
-
-        commit.raw_diffs
-      end
-    end
-  end
 end