Protect Git Refs

A git reference is a pointer to a particular commit. In the case of branches it is a pointer to the head of a line of work. For a tag, it’s a pointer to a particular commit that remains fixed. The purpose of this hook is to block changes to refs based on arbitrary conditions.

So, this does nothing other than reject the commit with the supplied message, if the provided condition evaluates to true. So, as a blank condition evaluates to true, unless you provide a condition this will reject everything (so not very useful).

The error message will only be used if one is not provided in the condition. If you want a dynamic error message based on the changes a user has pushed then you should use diagnosable conditions.

Click the Expand examples link to show examples…​ you will probably need to modify them to suit.

For example to prevent deletion of tags that begin with REL, you would start with the existing example for blocking all tag deletion, and end up with:

import com.atlassian.bitbucket.repository.RefChangeType refChanges.any { it.ref.id.startsWith("refs/tags/REL") && it.type == RefChangeType.DELETE }


To reject changes to certain subdirectories from users not in a particular authorized group, we need to combine two of the example conditions. Firstly, checking the group of the pusher, and secondly, checking if the user is in a group.

This leads us to the following condition script:

import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.bitbucket.auth.AuthenticationContext
import com.atlassian.bitbucket.user.UserService

def userService = ComponentLocator.getComponent(UserService)
def authContext = ComponentLocator.getComponent(AuthenticationContext)

if (pathsMatchExcludingDeletes('glob:path/to/sensitive/code/**')) {
    // return true if the user is NOT in the desired group, thus blocking the push
    return !userService.isUserInGroup(authContext.getCurrentUser(), "authorised-devs")
}
false

The intention of the examples is that you use them as starting points for more complex instructions, by and and or ing them together for instance.

When restricting pushes by file name, use pathsMatchExcludingDeletes rather than pathsMatch, as this will allow users to delete undesirable files that were in the repository before you started using this hook.