1

I have a scenario where on bitbucket I have assigned branch permissions but when the user does a commit on his local and tries to push that to a specific branch he comes to know the error at the time of push so its a rework for him to switch to other branch and again make a commit. So, I am thinking of a git hook like pre-push or pre-commit which can restrict user before the actual commit. Can anybody help me with the correct client side hook which can be implemented in such a case and why that hook should be used? PS: no server side hooks can be implemented.

Stack_IQ
  • 438
  • 5
  • 20

2 Answers2

2

This is not an easy problem to address with client-side hooks. Unlike server-side, where you expect every write to come in the form of a received push, client-side there are a lot of ways for the user to interact with the local repo. I know of no one hook that would catch all of them; and in fact, some of them might not be caught by any hook at all. (I can't think of a way to detect a local reset, or a fast-forward merge. If your workflow is such that the developers won't typically do those things, of course that helps.)

As always client-side hooks are only conveniences for the users who choose to use them. It sounds like that's fine for your use case, though keep in mind it does mean setup has to be done for each clone, and it means the permissions logic has to be visible (likely replicated, both for simplicity and to avoid breaking git's ability to operate independent of a central server) to each clone.

So, where would you start?

Well, pre-commit is the lowest-hanging fruit. The typical way to "accidentally" update a ref is, you have it checked out and you commit; and the first point in time where you can catch that (and abort it if desired) is pre-commit. You'd have to determine what branch (if any) will be updated - I think you'd use .git/HEAD for that.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • 1
    @Stack_IQ - You stated that the point is to catch the problem *earlier* and avoid re-work. `pre-push` won't tell you anything any sooner than the server-side permission checks. – Mark Adelsberger Jul 13 '18 at 13:24
  • @Mark..Thanks for the clarification! – Stack_IQ Jul 16 '18 at 06:21
  • @Stack_IQ, is there a particular reason why you do not mark user answers as accepted answers? If you are not aware how to, select the grey tick mark `✓` on the left of the answers so it becomes green. When you do this, it means you accepted the answer as a solution to you problem and it also closes your topic as solved. This will help future readers to easily find solutions to their similar issues. Additionally, you will earn 2 reputation points for each answer you mark correctly. – Gerhard Nov 05 '20 at 10:14
2

Like Mark Adelsberger, I think you want to use the pre-commit to catch the fact that the clients are not on the right branch as early as possible.

Here is an example of pre-commit script to detect if a branch is protected or not.

#!/bin/sh

# Generic function to verify if a word is part of a list of words (space-separated)
contains() {
    # 1 is the element to verify
    local element=$1
    shift
    # All other arguments are part of the list that may contain the element or not
    # so you don't need to quote the arg when calling this function
    local list="$@"

    case $list in
        $element                        |\
        $element[[:blank:]]*            |\
        *[[:blank:]]$element            |\
        *[[:blank:]]$element[[:blank:]]*)
            # The element is contained in the list
            return 0
            ;;
    esac
    # The element is not contained in the list
    return 1
}

# Space-separated list of branches that should not be committed on
protected_branches='devtool master'
current_branch=$(git rev-parse --abbrev-ref HEAD)

contains $current_branch $protected_branches
if [ $? -eq 0 ]; then
    echo The current branch $current_branch is protected! Create your own before committing.
    exit 1
fi

To address the issue of pushing the hooks to the client-side, there are a couple of SO posts related to that, here is one. In all cases, there is no straightforward way to do it.