You are viewing our old blog site. For latest posts, please visit us at the new space. Follow our publication there to stay updated with tech articles, tutorials, events & more.

Gitlab Force Push Update Hook

0.00 avg. rating (0% score) - 0 votes

Like any other organization we at Naukri use “Git” as version control system for our code and since most of our code is proprietary, we have one of the most popular solution to manage Git repositories on-premises i.e. Gitlab

There are various challenges faced during code collaboration and versioning while working with multiple teams / developers. One of them is “Force Push”. Usage of –force flag while pushing our code to Git is considered destructive as it unconditionally overwrites the remote repository with whatever you have locally, possibly overwriting any changes that a team member has pushed in the meantime. We would definitely want to restrict it.

While Gitlab does presents you with various options to restrict users to force push to specific branch in form of “Protected Branches”. What if you want to disable force push as a whole and restrict the user from “force” pushing any code to the repository.

Undermentioned is the code for update hook that can be used to do the same.

#!/usr/bin/env ruby

# This file was placed here by GitLab. It makes sure that your pushed commits
# will be processed properly.

BLANK_SHA = ('0' * 40).freeze
ref_name = ARGV[0]
old_value = ARGV[1]
new_value = ARGV[2]
repo_path = Dir.pwd

require_relative '../lib/gitlab_custom_hook'

if old_value != BLANK_SHA && new_value != BLANK_SHA
cmd = "git --git-dir=#{repo_path} rev-list #{old_value} ^#{new_value}"
missed_refs, _ = IO.popen(cmd).read
if (missed_refs.split("\n").size > 0)
puts "You are not allowed to force push code"
exit 1
end
end
if GitlabCustomHook.new.update(ref_name, old_value, new_value, repo_path)
exit 0
else
exit 1
end

 

The above mentioned file “update” should be placed within <home>/gitlab/gitlab-shell/hooks.

So, the way it works is that for every push the above mentioned hook receives the old commit hash and the new commit hash, using the command mentioned below it extracts the list of revision between the two commits

git --git-dir=#{repo_path} rev-list #{old_value} ^#{new_value}

In case, it finds there are missing refs between the two hashes that the user is trying to force push it exits with status code 1 and displays an error message “You are not allowed to force push code”.

** I know there are better ways in form of using –force-with-lease instead of –force while pushing the code and we do have number of blogs of explaining the same. However, above mentioned is the action that we chose to implement in case of Force Push.