Skip to content

Commit 867ad08

Browse files
avargitster
authored andcommitted
hooks: allow customizing where the hook directory is
Change the hardcoded lookup for .git/hooks/* to optionally lookup in $(git config core.hooksPath)/* instead. This is essentially a more intrusive version of the git-init ability to specify hooks on init time via init templates. The difference between that facility and this feature is that this can be set up after the fact via e.g. ~/.gitconfig or /etc/gitconfig to apply for all your personal repositories, or all repositories on the system. 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. Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent de0824e commit 867ad08

File tree

7 files changed

+71
-5
lines changed

7 files changed

+71
-5
lines changed

Documentation/config.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,23 @@ core.attributesFile::
618618
$XDG_CONFIG_HOME/git/attributes. If $XDG_CONFIG_HOME is either not
619619
set or empty, $HOME/.config/git/attributes is used instead.
620620

621+
core.hooksPath::
622+
By default Git will look for your hooks in the
623+
'$GIT_DIR/hooks' directory. Set this to different path,
624+
e.g. '/etc/git/hooks', and Git will try to find your hooks in
625+
that directory, e.g. '/etc/git/hooks/pre-receive' instead of
626+
in '$GIT_DIR/hooks/pre-receive'.
627+
+
628+
The path can be either absolute or relative. A relative path is
629+
taken as relative to the directory where the hooks are run (see
630+
the "DESCRIPTION" section of linkgit:githooks[5]).
631+
+
632+
This configuration variable is useful in cases where you'd like to
633+
centrally configure your Git hooks instead of configuring them on a
634+
per-repository basis, or as a more flexible and centralized
635+
alternative to having an `init.templateDir` where you've changed
636+
default hooks.
637+
621638
core.editor::
622639
Commands such as `commit` and `tag` that lets you edit
623640
messages by launching an editor uses the value of this

Documentation/githooks.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@ githooks - Hooks used by Git
77

88
SYNOPSIS
99
--------
10-
$GIT_DIR/hooks/*
10+
$GIT_DIR/hooks/* (or \`git config core.hooksPath`/*)
1111

1212

1313
DESCRIPTION
1414
-----------
1515

16-
Hooks are programs you can place in the `$GIT_DIR/hooks` directory to
17-
trigger actions at certain points in git's execution. Hooks that don't
18-
have the executable bit set are ignored.
16+
Hooks are programs you can place in a hooks directory to trigger
17+
actions at certain points in git's execution. Hooks that don't have
18+
the executable bit set are ignored.
19+
20+
By default the hooks directory is `$GIT_DIR/hooks`, but that can be
21+
changed via the `core.hooksPath` configuration variable (see
22+
linkgit:git-config[1]).
1923

2024
Before Git invokes a hook, it changes its working directory to either
2125
the root of the working tree in a non-bare repository, or to the

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ extern int shared_repository;
655655
extern const char *apply_default_whitespace;
656656
extern const char *apply_default_ignorewhitespace;
657657
extern const char *git_attributes_file;
658+
extern const char *git_hooks_path;
658659
extern int zlib_compression_level;
659660
extern int core_compression_level;
660661
extern int core_compression_seen;

config.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,9 @@ static int git_default_core_config(const char *var, const char *value)
717717
if (!strcmp(var, "core.attributesfile"))
718718
return git_config_pathname(&git_attributes_file, var, value);
719719

720+
if (!strcmp(var, "core.hookspath"))
721+
return git_config_pathname(&git_hooks_path, var, value);
722+
720723
if (!strcmp(var, "core.bare")) {
721724
is_bare_repository_cfg = git_config_bool(var, value);
722725
return 0;

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ int shared_repository = PERM_UMASK;
3333
const char *apply_default_whitespace;
3434
const char *apply_default_ignorewhitespace;
3535
const char *git_attributes_file;
36+
const char *git_hooks_path;
3637
int zlib_compression_level = Z_BEST_SPEED;
3738
int core_compression_level;
3839
int core_compression_seen;

run-command.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,10 @@ const char *find_hook(const char *name)
815815
static struct strbuf path = STRBUF_INIT;
816816

817817
strbuf_reset(&path);
818-
strbuf_git_path(&path, "hooks/%s", name);
818+
if (git_hooks_path)
819+
strbuf_addf(&path, "%s/%s", git_hooks_path, name);
820+
else
821+
strbuf_git_path(&path, "hooks/%s", name);
819822
if (access(path.buf, X_OK) < 0)
820823
return NULL;
821824
return path.buf;

t/t1350-config-hooks-path.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/sh
2+
3+
test_description='Test the core.hooksPath configuration variable'
4+
5+
. ./test-lib.sh
6+
7+
test_expect_success 'set up a pre-commit hook in core.hooksPath' '
8+
mkdir -p .git/custom-hooks .git/hooks &&
9+
write_script .git/custom-hooks/pre-commit <<-\EOF &&
10+
echo CUSTOM >>actual
11+
EOF
12+
write_script .git/hooks/pre-commit <<-\EOF
13+
echo NORMAL >>actual
14+
EOF
15+
'
16+
17+
test_expect_success 'Check that various forms of specifying core.hooksPath work' '
18+
test_commit no_custom_hook &&
19+
git config core.hooksPath .git/custom-hooks &&
20+
test_commit have_custom_hook &&
21+
git config core.hooksPath .git/custom-hooks/ &&
22+
test_commit have_custom_hook_trailing_slash &&
23+
git config core.hooksPath "$PWD/.git/custom-hooks" &&
24+
test_commit have_custom_hook_abs_path &&
25+
git config core.hooksPath "$PWD/.git/custom-hooks/" &&
26+
test_commit have_custom_hook_abs_path_trailing_slash &&
27+
cat >expect <<-\EOF &&
28+
NORMAL
29+
CUSTOM
30+
CUSTOM
31+
CUSTOM
32+
CUSTOM
33+
EOF
34+
test_cmp expect actual
35+
'
36+
37+
test_done

0 commit comments

Comments
 (0)