How to Prevent Remote Branch Deletion in Git Without Using Gitolite

How to prevent remote branch deletion in git without using gitolite

Yes, it is possible. Just add a suitable server side git hook.

You probably want to use a pre-receive hook. For details have a look at here or here.

Example:

#create repositories
git init a
git init --bare b

#add the hook in "b"
echo -e '#!/usr/bin/bash\nread old new ref\ntest $new != 0000000000000000000000000000000000000000' >>b/hooks/pre-receive
chmod +x b/hooks/pre-receive

#create a commit in "a"
cd a
echo foo >test
git add .
git commit -m testcommit

#push it to "b"
git push ../b master

#try to delete remote branch
git push ../b :master

How to allow remove remote branches at gitolite and forbid non fast forward

When you have to do checks that the core gitolite cannot do, it is time to bring in the VREF:

For every refex starting with VREF/FOO/ in a rule that applies to this user, a call to a program called FOO is triggered (location here).

So in your program 'FOO', you can check if the push is a non-fast-forward one (denied) or if it is a branch deletion (allowed).

GIT: How to protect the branch from being removed by other developers?

There are many ways to tackle this:

  1. Make another repo that's a sand box, and give readonly access to the master one. If they delete by accident they can get the branch from the master repo. This assumes you are only using github for your repos aside the local dev repos.
  2. Setup hooks in the repository that don't allow branches to be deleted unless you are a specific user. You can't do that on github as they won't allow arbitrary code to be executed on their servers. If you get a local repo instead, you can do this.
  3. Setup a local gitolite install to manage branches with permissions.

How to prevent users from deleting commit from remote git repository

With gitolite specifically, you have different types of permissions.

They include a 'D' for deletion:

repo @all
RWCD dummy-branch = foo

That will authorize the deletion of a branch dummy-branch, but that will also make all your existing RW+ rule deny deletion (because they don't have a 'D')

If a rule specifies RWD or RW+D, then rules that do NOT have the D qualifier will no longer permit deleting a ref.

In that case, you specify who has the right to delete, the others, by default, won't have that right.

Prevent users from pushing to deleted branch

You can't quite get at the --force or + flag, but you can have a pre-receive or update hook on the bare repository to which pushes are done.

In either kind of script you are told which reference(s) is/are to be updated. A branch is simply a reference whose full name starts with refs/heads/ (the remainder of the name is the branch name, which may include more slashes). You can check whether this is in a table of "forbidden" names and if so, reject the push.

(Other names begin with, e.g., refs/tags/ if they are tags, refs/notes/ if they are notes, and so on.)

The key difference between the pre-receive and update hooks is that the former is given a list of all proposed reference updates, all at once, on its standard input, while the latter is given proposed reference updates one at a time. Either can say "allow" or "deny", but because the pre-receive hook runs only once with all updates, its allow/deny is all-or-nothing: you inspect all updates once and determine at that time whether to allow all of them. The update hook runs once per reference and can deny some individual updates while permitting others.

Both hooks receive three items per update: the name, the previous (aka old) SHA-1, and the proposed new SHA-1. In both cases, a reference name is being created if the old SHA-1 is all-zeros; it's being deleted if the new SHA-1 is all-zeros; and it exists but is being moved from one commit1 to another if both SHA-1s are not the special all-zeros one.

Neither hook gets any indication of whether this is a forced push. That means that if you want to allow some method of deliberately re-creating one of these forbidden branches, you must come up with some alternative.

One possibility is to have certain "blessed" users: those who (at least in theory) know what they're doing are allowed to re-create such a branch. (This is usually the preferred solution, I believe.)

Another (rather hacky) method is to use multiple hooks. In the pre-receive hook, if one of the references to be updated has some special name (e.g., "refs/force"), allow the re-creation of branches; then, in an update hook, reject that particular special name, or use a post-receive hook to delete the "force" ref.

It's OK to have the pre-receive hook allow all, and then the update hook deny some: the result is simply to allow those that are not individually denied. The output seen by the users may be a little scary/confusing, though: they'll get a rejection message and have to realize that it's only for some particular ref update, not for the push as a whole.

You'd have to store the list of "deleted" branches somewhere (perhaps in a file maintained by the hooks, and updated as branches are deleted).

Note that if you use gitolite it has a lot of this kind of control built in. It takes over some of the hooks, and requires that everyone push as a particular user, so it operates a bit differently than just using the raw hooks the way I described above.


1Or tag or other object, but branch names should always point to commits. Tag names normally point either to commits (lightweight tags) or tag objects (annotated tags). It's possible to have a reference point directly to a blob or tree object but neither branch nor tag names should do so.

Deleting Git Repository Gitolite?

Nope! That's all you have to do!



Related Topics



Leave a reply



Submit