beside a main Git repository on a server (with Gitolite) I would like to have a possibility for each developer to set up a mirror it's own local repository. That's not difficult.
However, I want to disable git push --mirror
on the main Git server repository, to prevent mistakes if a developer screw the mirroring. I think the best place is a hook, maybe the update hook. But I cannot find how to detect in a server hook, that push --mirror
command has been executed on the client machine.
Client side solution is not possible because we use Eclipse Git (JGit), too.
If you really wanted to do this with hooks, the hook to use would be pre-receive
. You can't directly detect that it's a mirror push, because there's nothing about the data being sent that says it is, but you could be smart and get it right almost all the time. The pre-receive hook gets a list of refs to be updated, with old and new values, and if it exits with non-zero status, the entire push is aborted. Probably the main distinguishing feature of a mirror push is that it also pushes remote branches, as-is. I can't think of any normal cases you'd do this in, so you could just check for that, something like:
#!/bin/bash
while read old new ref; do
if [[ "$ref" =~ "^refs/remotes/.*" ]]; then
echo "You're pushing remote branches - did you use 'push --mirror'?"
echo "Rejecting push"
exit 1
fi
done
Any push --mirror
* would trip this hook, so it should cover you; it is of course a bit overzealous but unless you intend to maintain remote branches in your central repo, it won't matter.
*Except a really really manual one, where someone pushes from a repo with no remotes by manually specifying git push --mirror <url>
, but I really hope you don't have to worry about that.
I would still recommend gitolite. It doesn't exactly let you deny mirror pushes, but it can help somewhat, and provide a lot of other helpful things. Note that gitolite does allow you to add your own hooks, so wanting to use this shouldn't stop you from getting all the gitolite goodness. If you're not going to use Gitolite, you should really, really set core.logAllRefUpdates
to true in the central repo, so that if someone does get a bad push by you, you can recover.
Things related to this problem that gitolite would do for you:
- let you restrict most developers to only be able to access key branches, and prevent them from deleting anything (use
RW
, not RW+
permissions), so the damage they can do is limited - deletion of branches is probably the worst part of a push --mirror
- log access more fully, so that if someone does do damage, you can see exactly who it was and what they did, and avoid it in the future
I wouldn't try to 'patch up' security by using hooks. They weren't designed for this type of access control.
You could look at gitolite. It enables you to control access on a pre-branch basis.
See https://github.com/sitaramc/gitolite/wiki