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
diff --git a/lib/gitlab/ldap/access.rb b/lib/gitlab/ldap/access.rb
index cc8b14cc5babe736edddf273c720abc85e257d45..740f924f8d081279724606f1ac5ab689dac4e3e1 100644
--- a/lib/gitlab/ldap/access.rb
+++ b/lib/gitlab/ldap/access.rb
@@ -83,24 +83,39 @@ def update_permissions
 
       # Update user ssh keys if they changed in LDAP
       def update_ssh_keys
-        user.keys.ldap.where.not(key: ldap_user.ssh_keys).each do |deleted_key|
-          Rails.logger.info "#{self.class.name}: removing LDAP SSH key #{deleted_key.key} from #{user.name} (#{user.id})"
-          unless deleted_key.destroy
-            Rails.logger.error "#{self.class.name}: failed to remove LDAP SSH key #{key.inspect} from #{user.name} (#{user.id})"
-          end
-        end
+        remove_old_ssh_keys
+        add_new_ssh_keys
+      end
 
-        (ldap_user.ssh_keys - user.keys.ldap.pluck(:key)).each do |key|
-          Rails.logger.info "#{self.class.name}: adding LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})"
+      # Add ssh keys that are in LDAP but not in GitLab
+      def add_new_ssh_keys
+        keys = ldap_user.ssh_keys - user.keys.ldap.pluck(:key)
+
+        keys.each do |key|
+          logger.info "#{self.class.name}: adding LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})"
           new_key = LDAPKey.new(title: "LDAP - #{ldap_config.sync_ssh_keys}", key: key)
           new_key.user = user
+
           unless new_key.save
-            Rails.logger.error "#{self.class.name}: failed to add LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})\n"\
+            logger.error "#{self.class.name}: failed to add LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})\n"\
               "error messages: #{new_key.errors.messages}"
           end
         end
       end
 
+      # Remove ssh keys that do not exist in LDAP any more
+      def remove_old_ssh_keys
+        keys = user.keys.ldap.where.not(key: ldap_user.ssh_keys)
+
+        keys.each do |deleted_key|
+          logger.info "#{self.class.name}: removing LDAP SSH key #{deleted_key.key} from #{user.name} (#{user.id})"
+
+          unless deleted_key.destroy
+            logger.error "#{self.class.name}: failed to remove LDAP SSH key #{key.inspect} from #{user.name} (#{user.id})"
+          end
+        end
+      end
+
       # Update user email if it changed in LDAP
       def update_email
         return false unless ldap_user.try(:email)
@@ -142,7 +157,7 @@ def update_ldap_group_links
           if active_group_links.any?
             group.add_users([user.id], fetch_group_access(group, user, active_group_links), skip_notification: true)
           elsif group.last_owner?(user)
-            Rails.logger.warn "#{self.class.name}: LDAP group sync cannot remove #{user.name} (#{user.id}) from group #{group.name} (#{group.id}) as this is the group's last owner"
+            logger.warn "#{self.class.name}: LDAP group sync cannot remove #{user.name} (#{user.id}) from group #{group.name} (#{group.id}) as this is the group's last owner"
           else
             group.users.delete(user)
           end
@@ -175,6 +190,7 @@ def admin_group
       end
 
       private
+
       def gitlab_groups_with_ldap_link
         ::Group.includes(:ldap_group_links).references(:ldap_group_links).
           where.not(ldap_group_links: { id: nil }).
@@ -190,6 +206,10 @@ def fetch_group_access(group, user, active_group_links)
         # TODO: Test if nil value of current_access_level in handled properly
         [current_access_level, max_group_access_level].compact.max
       end
+
+      def logger
+        Rails.logger
+      end
     end
   end
 end