46

Not sure if this is possible in git (I haven't found it but I may be using the wrong vocabulary in my searches), but it be would useful to be able to modify and enable hooks as the defaults for all new repositories (at the time of creation I mean) so these don't have to be customized each time a new repository is created. It seems the easy way to do this is write a wrapper that sets my hooks and chmods them when I create a new repository, but if there's a way built into git I would rather use that instead of having unnecessary wrapper scripts however little lying around.


Clarification copied up from a comment to a now-deleted answer:

My question is whether the default behavior for ALL new repositories can be changed, so they don't need to be customized in the same way each time for each new repository. The easy answer is write a wrapper for creating and customizing the repos (it generates the hook scripts and chmods them), but it seems like this default behavior should also be customizable without having to do that.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
rplevy
  • 5,393
  • 3
  • 32
  • 31
  • 1
    Don't forget that answers can be deleted - it is often better to clarify your question than to add comments to answers. – Jonathan Leffler Dec 30 '09 at 00:09
  • 1
    With git 2.9 (June 2016), you will have a new config to define a central place for hooks for all repos: **`core.hooksPath`**. See [my answer below](http://stackoverflow.com/a/37293001/6309) – VonC May 18 '16 at 07:34

4 Answers4

45

With git 2.9, you have a new option made for centralizing hooks: core.hooksPath

See commit 867ad08, commit de0824e, commit bf7d977, commit 49fa52f (04 May 2016) by Ævar Arnfjörð Bjarmason (avar).
(Merged by Junio C Hamano -- gitster -- in commit 6675f50, 17 May 2016)

The git config documentation now includes:

core.hooksPath

By default Git will look for your hooks in the '$GIT_DIR/hooks' directory.
Set this to different path, e.g. '/etc/git/hooks', and Git will try to find your hooks in that directory, e.g. '/etc/git/hooks/pre-receive' instead of in '$GIT_DIR/hooks/pre-receive'.

The path can be either absolute or relative. A relative path is taken as relative to the directory where the hooks are run

This configuration variable is useful in cases where you'd like to centrally configure your Git hooks instead of configuring them on a per-repository basis, or as a more flexible and centralized alternative to having an init.templateDir where you've changed default hooks.

The author of this pathc (Ævar Arnfjörð Bjarmason avar) adds in his commit:

I plan on using this on a centralized Git server where users can create arbitrary repositories under /gitroot, but I'd like to manage all the hooks that should be run centrally via a unified dispatch mechanism.


Git 2.10 uses that new setting in git rev-parse --git-path hooks/<hook>

See commit 9445b49 (16 Aug 2016) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit d05d0e9, 19 Aug 2016)

rev-parse: respect core.hooksPath in --git-path

The idea of the --git-path option is not only to avoid having to prefix paths with the output of --git-dir all the time, but also to respect overrides for specific common paths inside the .git directory
(e.g. git rev-parse --git-path objects will report the value of the environment variable GIT_OBJECT_DIRECTORY, if set).

When introducing the core.hooksPath setting, we forgot to adjust git_path() accordingly. This patch fixes that.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 4
    Worth noting that this prevents any `.git/hooks` from running as of 2.19. I wish they had implemented a better fallback mechanism, e.g. if you have `.git/hook`, use that instead, or run both. – Ciro Santilli OurBigBook.com Nov 28 '18 at 07:54
  • 1
    @CiroSantilli新疆改造中心六四事件法轮功 What changed in the recent 2.19 which prevent `.git/hooks` from running? – VonC Nov 28 '18 at 08:14
  • 2
    @CiroSantilli新疆改造中心六四事件法轮功 OK, the "as of" through me off there. That could be a good idea of an evolution to propose to the Git mailing list: a "`hooksPathMode`": "`exclusive`" (only search in one path) or "`combined`" (search first in `hooksPath`, falls back to `./hooks`). Default: "`exlusive`" (current mode) – VonC Nov 28 '18 at 08:21
  • 1
    @CiroSantilli新疆改造中心法轮功六四事件 Your question: [Git global hooks and project hooks](https://stackoverflow.com/q/51178382/94687) – imz -- Ivan Zakharyaschev Feb 29 '20 at 03:49
  • Does this affect git hooks on the server side as well? Or just the client hooks? – DrBeco Jun 26 '23 at 00:55
  • @DrBeco It affects only the machine on which you are executing the command. If that machine is a "server" (a repository hosting server), then it would affect the server. If it is your machine, a client, then it affects the client. – VonC Jun 26 '23 at 06:01
  • Thanks for the reply. I should've made my question clearer. So, I have a server, and hooks are in two places. The "server" side hooks are at `/srv/git/hooks` and the client hooks are as usual `$GIT_DIR/.git/hooks`. My first attempt on testing shows that this command unify all hooks, and you lose the hability to have them both. I wonder if this is so, or if I have options here. – DrBeco Jun 26 '23 at 15:00
  • @DrBeco Your server process should run with a different service account than your client process. That way, each one can define their own `core.hooksPath` in their respective `$HOME/.gitconfig` global Git configuration. – VonC Jun 26 '23 at 15:47
39

From the git-init man page (also works with git-clone if you are cloning an existing repo instead of creating a new one from scratch):

       --template=<template_directory>
           Provide the directory from which templates will be used. The
           default template directory is /usr/share/git-core/templates.

           When specified, <template_directory> is used as the source of the
           template files rather than the default. The template files include
           some directory structure, some suggested "exclude patterns", and
           copies of non-executing "hook" files. The suggested patterns and
           hook files are all modifiable and extensible.

You can modify the system-wide template directory (which defaults to /usr/share/git-core/templates, but may be in a different location on your machine), you can supply --template=<template_directory> on the command line when you create or clone the repo, or you can configure the default template directory in your config file:

[init]
     templatedir = /path/to/templates
Brian Campbell
  • 322,767
  • 57
  • 360
  • 340
  • But the hook files will end up non-executable on fresh clones, which is reassuring to know. – ndim Dec 30 '09 at 00:46
  • But, if someone uses their own git installation or clones from a remote machine (say, over ssh) then the hooks won't be copied. – Pat Notz Dec 30 '09 at 03:55
  • Right. This is only useful for setting up a default set of hooks for yourself on your own machine. If you want to have everyone on the same team using the same set of hooks, you're going to need a wrapper script or something of the sort. – Brian Campbell Dec 30 '09 at 04:01
5

With git 1.6.5.3 (and some earlier versions), you get sample hooks delivered in your .git/hooks directory:

$ ls .git/hooks
applypatch-msg.sample     post-update.sample        prepare-commit-msg.sample
commit-msg.sample         pre-applypatch.sample     update.sample
post-commit.sample        pre-commit.sample
post-receive.sample       pre-rebase.sample
$ 

They are all executable on my system. To make use of one of the hooks, either copy or rename the file removing the '.sample' suffix. Edit it as appropriate to suit your requirements.


Addressing the question in a comment - to change the default sample hooks installed, you need to find the directory where git is installed. On my machine, that is $HOME/git - so the binary is in $HOME/git/bin/git. Then the directory containing the sample hooks is:

$HOME/git/share/git-core/templates/hooks

If you edit those templates (be careful), then that is what will be copied to new git repositories. They'll still be samples, but they'll be your samples.

I've not experimented with creating a non-sample file in the directory; it might or might not be copied. Be wary of changing the defaults, though - when you next upgrade, you'll have to redo the changes.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • This also doesn't answer the question I asked... See clarification in my response to John Feminella's reply, which he responded to. – rplevy Dec 29 '09 at 23:51
  • 2
    @rplevy: I can see the clarification since I have enough rep to see deleted answers; other people cannot (including you). Edit your question to match. I think my answer does address your question, but I'm biassed. Specifically, one way to change the default templates installed is to edit the files that are copied by 'git init', which is what I said. Brian Campbell also pointed out that there is a way to configure 'git init' to use a non-standard location, but ensuring that the non-standard option is applied could be interesting. You might need to investigate the system configuration. – Jonathan Leffler Dec 30 '09 at 00:06
  • Thanks, either I misread your answer at first pass or it was elaborated on since. This does indeed answer my question. Re: "when you next upgrade, you'll have to redo the changes" that depends, I think apt may prompt you. And also the files can be maintained separately. Symbolically linked I suppose would be a good way to do it. – rplevy Dec 30 '09 at 00:14
  • @rplevy: OK - there was a small window when the material below the rule was not present; I guess you looked at the answer then, and didn't see the update which was done within 5 minutes of the posting (so it didn't count as an edit of the posting). I don't know whether apt would prompt you or not. Symlinks might help; I wouldn't rely on it without experimentation because I can see a number of ways in which upgrades could clobber your modifications (and I would keep the templates under git control!). – Jonathan Leffler Dec 30 '09 at 00:29
  • 1
    This totally worked. This deserves wayyyy more upvotes. – MrPickles Aug 12 '15 at 11:40
0

For MacPorts dorectory will be /opt/local/share/git-core/templates/

To share hooks or templates with team members I usually create subdirectory in project like $PROJECT_DIR/lib/git/hooks then create Rake task or shell script to copy cp $PROJECT_DIR/git/hooks/* $PROJECT_DIR/.git/hooks. Symbolic links doesn't work.

A B
  • 2,013
  • 2
  • 21
  • 22