nowox
nowox

Reputation: 29106

How to prevent developers to push on a particular branch?

We've recently changed feature name from foo to bar. This is a good opportunity to create a new branch at the latest master state from which the work will go on.

The previous branch needs to be kept for its history and I cannot be deleted yet.

Therefore I would like to find a mechanism that prevent confused developers to push changes on the wrong branch. My trick is:

$ git checkout feature/foo
$ git commit --allow-empty -m "WARNING: DO NOT COMMIT on this branch"
$ git push

Unfortunately I would prefer a solution like

$ git branch --lock feature/foo -m "Use feature/bar instead"
$ git push  

What other option could I use?

Note: I can also rename the current branch git branch -m feature/foo feature/bar, but this is off topic.

Upvotes: 1

Views: 453

Answers (2)

DUman
DUman

Reputation: 2590

This sounds like something you would want to use git hooks for. The pre-push hook can quite easily specify such a limitation.

In the .git/hooks folder, create a script called pre-push. The contents should be a Bash script that returns 1 in case you want to prevent the push. My first idea of it is along these lines:

#!/bin/bash
locked_branch='feature/foo'
push_branch=$(git rev-parse --abbrev-ref HEAD)

if [ "$locked_branch" = "$push_branch" ]
then
    echo "Do not push this branch! Use feature/bar instead"
    exit 1
fi
exit 0

EDIT:

The above is of course given the constraint that there's no proper server that would run hooks. In the presence of a server however, it should be the update script on the server-side enforcing this, the first parameter of which is the branch being updated. So it would work with a check like

if [ "$locked_branch" = "$1" ]

instead of having a push_branch variable, based on the first script posted.

Upvotes: 1

torek
torek

Reputation: 488453

This is the sort of thing that pre-receive and update hooks are designed for.

Establishing such a hook on the server requires access to the server. You do not mention whether this is your own server, or some "git as a service" (GaaS?) provider. Providers always have their own private methods of establishing hooks since, for security reasons, they do not give you full access to the server.

If it is your own private server, create a hook, in whatever language you like. Check whether an incoming reference change (in pre-receive) or the requested reference change (in update) is for the branch feature/foo. If so, print an error message for the user: this error will be copied to their machine, prefixed with remote:.

#! /bin/sh
status=0
while read oldsha newsha refname; do
    case $refname in
    refs/heads/feature/foo)
        echo "branch feature/foo is deprecated, use feature/bar" 1>&2
        status=1
        ;;
    esac
done
exit $status

(an example pre-receive hook).

Note that using a pre-receive hook, rejection will reject the entire push, i.e., if I were attempting to push both feature/foo and personal/blah, I would see:

remote: branch feature/foo is deprecated, use feature/bar

and my push would fail, with personal/blah not being updated either.

Using an update hook, my push would half-fail and half-succeed: I would see the same error message and feature/foo would not get pushed, but personal/blah would.

Upvotes: 1

Related Questions