diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 4b4bc3d4276b8e85de9333086b8d26a91150b2d8..428a42266d0e12ec484a5b78b0be596ad0acce83 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -1,10 +1,10 @@
 module BlobHelper
-  def highlighter(blob_name, blob_content, nowrap: false)
-    Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap)
+  def highlighter(blob_name, blob_content, repository: nil, nowrap: false)
+    Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap, repository: repository)
   end
 
-  def highlight(blob_name, blob_content, nowrap: false, plain: false)
-    Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, plain: plain)
+  def highlight(blob_name, blob_content, repository: nil, nowrap: false, plain: false)
+    Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, plain: plain, repository: repository)
   end
 
   def no_highlight_files
diff --git a/app/models/repository.rb b/app/models/repository.rb
index acc720ccfa32b1575224d1f1fa6a03476d06a2c4..2a6a3b086c200282120f5bf5a0e3c4c67b336d85 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -978,6 +978,10 @@ class Repository
     raw_repository.ls_files(actual_ref)
   end
 
+  def gitattribute(path, name)
+    raw_repository.attributes(path)[name]
+  end
+
   def copy_gitattributes(ref)
     actual_ref = ref || root_ref
     begin
diff --git a/app/views/projects/blob/_text.html.haml b/app/views/projects/blob/_text.html.haml
index b1769759dce7a62e1c4368ebe50d2b782a44af8e..58524418a6786d3d5619128a8375e2955b780599 100644
--- a/app/views/projects/blob/_text.html.haml
+++ b/app/views/projects/blob/_text.html.haml
@@ -16,4 +16,4 @@
       .file-content.code
         .nothing-here-block Empty file
     - else
-      = render 'shared/file_highlight', blob: blob
+      = render 'shared/file_highlight', blob: blob, repository: @repository
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index ad944a19ca11b64f6e526d66aa71b7dcf6510fbb..e26693bf5b9613a0419b520b10e983371e6d1e9f 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -1,3 +1,5 @@
+- repository = nil unless local_assigns.key?(:repository)
+
 .file-content.code.js-syntax-highlight
   .line-numbers
     - if blob.data.present?
@@ -11,4 +13,4 @@
           = link_icon
           = i
   .blob-content{data: {blob_id: blob.id}}
-    = highlight(blob.name, blob.data, plain: blob.no_highlighting?)
+    = highlight(blob.path, blob.data, repository: repository, plain: blob.no_highlighting?)
diff --git a/lib/gitlab/blame.rb b/lib/gitlab/blame.rb
index 997a22779a0406ba08e9a749dcb1ab54c38b8488..d62bc50ce78e06536cb276d3432fe024d88837b2 100644
--- a/lib/gitlab/blame.rb
+++ b/lib/gitlab/blame.rb
@@ -41,7 +41,8 @@ module Gitlab
 
     def highlighted_lines
       @blob.load_all_data!(repository)
-      @highlighted_lines ||= Gitlab::Highlight.highlight(@blob.name, @blob.data).lines
+      @highlighted_lines ||=
+        Gitlab::Highlight.highlight(@blob.path, @blob.data, repository: repository).lines
     end
 
     def project
diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb
index 280120b0f9eb04a04aee5b18849a384229009930..2ba934a85c5148d05ee16579e64e1fdca0365824 100644
--- a/lib/gitlab/highlight.rb
+++ b/lib/gitlab/highlight.rb
@@ -1,7 +1,8 @@
 module Gitlab
   class Highlight
-    def self.highlight(blob_name, blob_content, nowrap: true, plain: false)
-      new(blob_name, blob_content, nowrap: nowrap).
+    def self.highlight(blob_name, blob_content,
+                       repository: nil, nowrap: true, plain: false)
+      new(blob_name, blob_content, nowrap: nowrap, repository: repository).
         highlight(blob_content, continue: false, plain: plain)
     end
 
@@ -10,12 +11,29 @@ module Gitlab
       return [] unless blob
 
       blob.load_all_data!(repository)
-      highlight(file_name, blob.data).lines.map!(&:html_safe)
+      highlight(file_name, blob.data, repository: repository).lines.map!(&:html_safe)
     end
 
-    def initialize(blob_name, blob_content, nowrap: true)
+    attr_reader :lexer
+    def initialize(blob_name, blob_content, repository: nil, nowrap: true)
+      @blob_name = blob_name
+      @blob_content = blob_content
+      @repository = repository
       @formatter = rouge_formatter(nowrap: nowrap)
-      @lexer = Rouge::Lexer.guess(filename: blob_name, source: blob_content).new rescue Rouge::Lexers::PlainText
+
+      @lexer = custom_language || begin
+        Rouge::Lexer.guess(filename: blob_name, source: blob_content).new
+      rescue Rouge::Lexer::AmbiguousGuess => e
+        e.alternatives.sort_by(&:tag).first
+      end
+    end
+
+    def custom_language
+      return nil if @repository.nil?
+
+      language_name = @repository.gitattribute(@blob_name, 'gitlab-language')
+
+      Rouge::Lexer.find(language_name)
     end
 
     def highlight(text, continue: true, plain: false)
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index 1620eb6c60adb507920d56cd7cbf47b8828961a5..303943606ff35e048dbca5c7357fc7d003b6f1b5 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -18,4 +18,14 @@ describe Gitlab::Highlight, lib: true do
     end
   end
 
+  describe 'custom highlighting from .gitattributes' do
+    let(:blob) { project.blob_at_branch('master', 'custom-highlighting/test.gitlab-custom') }
+    let(:highlighter) {
+      Gitlab::Highlight.new(blob.path, blob.contents, repository: project.repository)
+    }
+
+    it 'highlights as ruby' do
+      expect(highlighter.lexer).to be_an_instance_of Rouge::Lexers::Ruby
+    end
+  end
 end