diff --git a/app/models/git_hook.rb b/app/models/git_hook.rb
index e48a399d6009658fa6bfeab49fe18e6d0c9d2373..1de3116b62124a1b3c60a5296a44ecd1b302be95 100644
--- a/app/models/git_hook.rb
+++ b/app/models/git_hook.rb
@@ -2,24 +2,30 @@ class GitHook < ActiveRecord::Base
   belongs_to :project
 
   validates :project, presence: true, unless: "is_sample?"
-  
+
+  def commit_validation?
+    commit_message_regex.present? ||
+      author_email_regex.present? ||
+      member_check ||
+      file_name_regex.present? ||
+      max_file_size > 0
+  end
+
   def commit_message_allowed?(message)
-    if commit_message_regex.present?
-      if message =~ Regexp.new(commit_message_regex)
-        true
-      else
-        false
-      end
+    data_valid?(message, commit_message_regex)
+  end
+
+  def author_email_allowed?(email)
+    data_valid?(email, author_email_regex)
+  end
+
+  private
+
+  def data_valid?(data, regex)
+    if regex.present?
+      !!(data =~ Regexp.new(regex))
     else
       true
     end
   end
-
-  def commit_validation?
-    commit_message_regex.present? || 
-      author_email_regex.present? || 
-      member_check || 
-      file_name_regex.present? || 
-      max_file_size > 0
-  end
 end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index ee89c5052c0ff6b2683e4986070d29a0830896ef..b344ff84503b33eb7c8b7f0d09bc80e85a960f50 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -170,9 +170,9 @@ def forced_push?(oldrev, newrev)
     end
 
     def git_hook_check(user, project, ref, oldrev, newrev)
-      return build_status_object(true) unless project.git_hook
-
-      return build_status_object(true) unless newrev && oldrev
+      unless project.git_hook && newrev && oldrev
+        return build_status_object(true)
+      end
 
       git_hook = project.git_hook
 
@@ -182,8 +182,9 @@ def git_hook_check(user, project, ref, oldrev, newrev)
           return build_status_object(false, "You can not delete tag")
         end
       else
-        return build_status_object(true) unless git_hook.commit_validation?
-        return build_status_object(true) if Gitlab::Git.blank_ref?(newrev)
+        if Gitlab::Git.blank_ref?(newrev) || !git_hook.commit_validation?
+          return build_status_object(true)
+        end
 
         oldrev = project.default_branch if Gitlab::Git.blank_ref?(oldrev)
 
@@ -195,61 +196,76 @@ def git_hook_check(user, project, ref, oldrev, newrev)
           end
 
         commits.each do |commit|
-          if git_hook.commit_message_regex.present?
-            unless commit.safe_message =~ Regexp.new(git_hook.commit_message_regex)
-              return build_status_object(false, "Commit message does not follow the pattern '#{git_hook.commit_message_regex}'")
-            end
+          if status_object = check_commit(commit, git_hook)
+            return status_object
           end
+        end
+      end
 
-          if git_hook.author_email_regex.present?
-            unless commit.committer_email =~ Regexp.new(git_hook.author_email_regex)
-              return build_status_object(false, "Committer's email '#{commit.committer_email}' does not follow the pattern '#{git_hook.author_email_regex}'")
-            end
+      build_status_object(true)
+    end
 
-            unless commit.author_email =~ Regexp.new(git_hook.author_email_regex)
-              return build_status_object(false, "Author's email '#{commit.author_email}' does not follow the pattern '#{git_hook.author_email_regex}'")
-            end
-          end
+    private
+
+    # If commit does not pass git hook validation the whole push should be rejected.
+    # This method should return nil if no error found or status object if there are some errors.
+    # In case of errors - all other checks will be canceled and push will be rejected.
+    def check_commit(commit, git_hook)
+      unless git_hook.commit_message_allowed?(commit.safe_message)
+        return build_status_object(false, "Commit message does not follow the pattern '#{git_hook.commit_message_regex}'")
+      end
+
+      unless git_hook.author_email_allowed?(commit.committer_email)
+        return build_status_object(false, "Committer's email '#{commit.committer_email}' does not follow the pattern '#{git_hook.author_email_regex}'")
+      end
+
+      unless git_hook.author_email_allowed?(commit.author_email)
+        return build_status_object(false, "Author's email '#{commit.author_email}' does not follow the pattern '#{git_hook.author_email_regex}'")
+      end
+
+      # Check whether author is a GitLab member
+      if git_hook.member_check
+        unless User.existing_member?(commit.author_email.downcase)
+          return build_status_object(false, "Author '#{commit.author_email}' is not a member of team")
+        end
 
-          # Check whether author is a GitLab member
-          if git_hook.member_check
-            unless User.existing_member?(commit.author_email.downcase)
-              return build_status_object(false, "Author '#{commit.author_email}' is not a member of team")
-            end
-
-            if commit.author_email.downcase != commit.committer_email.downcase
-              unless User.existing_member?(commit.committer_email.downcase)
-                return build_status_object(false, "Committer '#{commit.committer_email}' is not a member of team")
-              end
-            end
+        if commit.author_email.downcase != commit.committer_email.downcase
+          unless User.existing_member?(commit.committer_email.downcase)
+            return build_status_object(false, "Committer '#{commit.committer_email}' is not a member of team")
           end
+        end
+      end
+
+      if status_object = check_commit_diff(commit, git_hook)
+        return status_object
+      end
 
-          if git_hook.file_name_regex.present?
-            commit.diffs.each do |diff|
-              if (diff.renamed_file || diff.new_file) && diff.new_path =~ Regexp.new(git_hook.file_name_regex)
-                return build_status_object(false, "File name #{diff.new_path.inspect} does not follow the pattern '#{git_hook.file_name_regex}'")
-              end
-            end
+      nil
+    end
+
+    def check_commit_diff(commit, git_hook)
+      if git_hook.file_name_regex.present?
+        commit.diffs.each do |diff|
+          if (diff.renamed_file || diff.new_file) && diff.new_path =~ Regexp.new(git_hook.file_name_regex)
+            return build_status_object(false, "File name #{diff.new_path.inspect} does not follow the pattern '#{git_hook.file_name_regex}'")
           end
+        end
+      end
 
-          if git_hook.max_file_size > 0
-            commit.diffs.each do |diff|
-              next if diff.deleted_file
+      if git_hook.max_file_size > 0
+        commit.diffs.each do |diff|
+          next if diff.deleted_file
 
-              blob = project.repository.blob_at(commit.id, diff.new_path)
-              if blob.size > git_hook.max_file_size.megabytes
-                return build_status_object(false, "File #{diff.new_path.inspect} is larger than the allowed size of #{git_hook.max_file_size} MB")
-              end
-            end
+          blob = project.repository.blob_at(commit.id, diff.new_path)
+          if blob.size > git_hook.max_file_size.megabytes
+            return build_status_object(false, "File #{diff.new_path.inspect} is larger than the allowed size of #{git_hook.max_file_size} MB")
           end
         end
       end
 
-      build_status_object(true)
+      nil
     end
 
-    private
-
     def protected_branch_action(oldrev, newrev, branch_name)
       # we dont allow force push to protected branch
       if forced_push?(oldrev, newrev)
@@ -290,8 +306,6 @@ def tag_name(ref)
       end
     end
 
-    protected
-
     def build_status_object(status, message = '')
       GitAccessStatus.new(status, message)
     end