Short answer:
No. There's no built-in git feature that would allow you to invisibly install client-side hooks from the server.
Long answer:
Yes. Whilst there's no built-in way to invisibly install client-side hooks (nor should there be), if you have control over the machines your team is using (e.g. the ability to assert group policy or run administrative commands on behalf of the user) then there are ways to achieve what you're after.
Full disclosure: I work on Atlassian's Premier Support team, and pretty closely along side our Bitbucket Server developers. Having said that, this is almost entirely a git matter, not a Bitbucket one, so I'll focus on that here.
Option 1: Override core.hooksPath
(see also: https://git-scm.com/docs/githooks)
By default git looks for hooks inside your repository in $GIT_DIR/hooks/*
. This is configurable on both a per-repo level and on a global level. Configuring this globally is pretty simple:
git config --global core.hooksPath /path/to/custom/hooks
This will take more or less immediate effect for all repositories, both new and existing. You need some way to run this on each team member's workstation, but most corporate environments already have methods of running scripts etc. remotely so this is really just a matter of convincing your IT admin team that it's a necessary business requirement.
Of course, to actually use your custom hooks, you either need to ensure you're using a path that's universally accessible (an auto-mounted location) or — probably safer — copy the hooks locally to their machines. Again, I am expecting you have mechanisms to do this, or can run scripts remotely to achieve the same effect.
If you want to give the core.hooksPath
setting a try on your local machine, do the following:
$ mkdir ~/.globalgithooks
$ echo "printf 'hello world\n'" > ~/.globalgithooks/pre-commit
$ chmod +x ~/.globalgithooks/pre-commit
$ git config --global core.hooksPath ~/.globalgithooks
Then find some repos (new or existing) you can safely make some dummy commits to and you'll see it working.
Pros:
- Takes effect for both current and newly created repositories
Cons:
- Removes the ability to customise hooks on a per-repo basis
Option 2: Override the git template dir
(see also: https://git-scm.com/docs/git-init#_template_directory)
When you create a repository, git doesn't just set it up from "nothing"; it uses a pre-packaged template directory which contains (to quote the above link) 'some directory structure, suggested "exclude patterns", and sample hook files.' You can add your own custom hooks to this template directory and whenever a new repository is created, they will be copied over to that repository's local set of hooks ($GIT_DIR/hooks
). Fun fact: even when you clone a repository, you're still creating a "new" one — it's simply a new repository that git then adds an upstream remote URL, fetches objects and checks out the default branch for. In other words, the template directory still gets used when cloning, so custom hooks created there will automatically be set up for any repository created by cloning.
Again, you'd need some kind of managed access to your machines to do this. However it's arguably more complicated than the first option; where with option 1 you can simply copy over your hooks anywhere you like and run a straightforward git config
command, for this option to work you need to locate the correct template directory for that user's git installation. Given the myriad ways git might be installed on different operating systems and by different package managers, this means you need to determine where the directory is located. By default in Linux this is /usr/share/git-core/templates
; on my homebrew install on macOS this can be found either at /usr/local/Cellar/git/$GIT_VERSION/share/git-core/templates
with a symbolic link available at /usr/local/share/git-core/templates
… in other words, you'd need to cobble together some kind of logic to find the right place and add your hooks there. And even then, this won't affect any existing repositories already on the machine.
An alternative approach would be to set init.templateDir
in your global git configuration, obviating the need to locate the existing temp dir. This however forces you to maintain everything — if in future some fundamental part of that structure changed, you would need to maintain and update your copy.
Pros:
- Configures hooks on a per-repo basis, meaning you can continue to use other per-repo hooks as desired
Cons:
- Only affects new (initialized and cloned) repos; existing repos will not know about new additions to your template directory
- Potentially brittle to configure due to the need to determine the user's git install location (or else fully maintain your own custom template directory)
For both options, you'd need to figure out how often to run these to ensure your hooks are kept up to date. You could run these on a regular interval, or simply push to all client machines whenever you make a change — it all depends on your administrative tooling
No matter how you go about this, the savvy user will always be able to get around it, but I'm guessing this is not an issue in most cases. If your developers are actively circumventing a hook that tells them not to commit something so they can do it anyway, then that ceases to be a technical issue and becomes a management one.