Merge branch 'ab/hooks'

A new configuration variable core.hooksPath allows customizing
where the hook directory is.

* ab/hooks:
  hooks: allow customizing where the hook directory is
  githooks.txt: minor improvements to the grammar & phrasing
  githooks.txt: amend dangerous advice about 'update' hook ACL
  githooks.txt: improve the intro section
This commit is contained in:
Junio C Hamano 2016-05-17 14:38:17 -07:00
commit 6675f501f6
8 changed files with 112 additions and 32 deletions

View File

@ -618,6 +618,23 @@ core.attributesFile::
$XDG_CONFIG_HOME/git/attributes. If $XDG_CONFIG_HOME is either not
set or empty, $HOME/.config/git/attributes is used instead.
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 (see
the "DESCRIPTION" section of linkgit:githooks[5]).
+
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.
core.editor::
Commands such as `commit` and `tag` that lets you edit
messages by launching an editor uses the value of this

View File

@ -130,7 +130,12 @@ The template directory will be one of the following (in order):
- the default template directory: `/usr/share/git-core/templates`.
The default template directory includes some directory structure, suggested
"exclude patterns" (see linkgit:gitignore[5]), and sample hook files (see linkgit:githooks[5]).
"exclude patterns" (see linkgit:gitignore[5]), and sample hook files.
The sample hooks are all disabled by default, To enable one of the
sample hooks rename it by removing its `.sample` suffix.
See linkgit:githooks[5] for more general info on hook execution.
EXAMPLES
--------

View File

@ -7,24 +7,35 @@ githooks - Hooks used by Git
SYNOPSIS
--------
$GIT_DIR/hooks/*
$GIT_DIR/hooks/* (or \`git config core.hooksPath`/*)
DESCRIPTION
-----------
Hooks are little scripts you can place in `$GIT_DIR/hooks`
directory to trigger action at certain points. When
'git init' is run, a handful of example hooks are copied into the
`hooks` directory of the new repository, but by default they are
all disabled. To enable a hook, rename it by removing its `.sample`
suffix.
Hooks are programs you can place in a hooks directory to trigger
actions at certain points in git's execution. Hooks that don't have
the executable bit set are ignored.
NOTE: It is also a requirement for a given hook to be executable.
However - in a freshly initialized repository - the `.sample` files are
executable by default.
By default the hooks directory is `$GIT_DIR/hooks`, but that can be
changed via the `core.hooksPath` configuration variable (see
linkgit:git-config[1]).
This document describes the currently defined hooks.
Before Git invokes a hook, it changes its working directory to either
the root of the working tree in a non-bare repository, or to the
$GIT_DIR in a bare repository.
Hooks can get their arguments via the environment, command-line
arguments, and stdin. See the documentation for each hook below for
details.
'git init' may copy hooks to the new repository, depending on its
configuration. See the "TEMPLATE DIRECTORY" section in
linkgit:git-init[1] for details. When the rest of this document refers
to "default hooks" it's talking about the default template shipped
with Git.
The currently supported hooks are described below.
HOOKS
-----
@ -32,15 +43,15 @@ HOOKS
applypatch-msg
~~~~~~~~~~~~~~
This hook is invoked by 'git am' script. It takes a single
This hook is invoked by 'git am'. It takes a single
parameter, the name of the file that holds the proposed commit
log message. Exiting with non-zero status causes
'git am' to abort before applying the patch.
log message. Exiting with a non-zero status causes 'git am' to abort
before applying the patch.
The hook is allowed to edit the message file in place, and can
be used to normalize the message into some project standard
format (if the project has one). It can also be used to refuse
the commit after inspecting the message file.
format. It can also be used to refuse the commit after inspecting
the message file.
The default 'applypatch-msg' hook, when enabled, runs the
'commit-msg' hook, if the latter is enabled.
@ -73,10 +84,10 @@ pre-commit
~~~~~~~~~~
This hook is invoked by 'git commit', and can be bypassed
with `--no-verify` option. It takes no parameter, and is
with the `--no-verify` option. It takes no parameters, and is
invoked before obtaining the proposed commit log message and
making a commit. Exiting with non-zero status from this script
causes the 'git commit' to abort.
making a commit. Exiting with a non-zero status from this script
causes the 'git commit' command to abort before creating a commit.
The default 'pre-commit' hook, when enabled, catches introduction
of lines with trailing whitespaces and aborts the commit when
@ -115,15 +126,15 @@ commit-msg
~~~~~~~~~~
This hook is invoked by 'git commit', and can be bypassed
with `--no-verify` option. It takes a single parameter, the
with the `--no-verify` option. It takes a single parameter, the
name of the file that holds the proposed commit log message.
Exiting with non-zero status causes the 'git commit' to
Exiting with a non-zero status causes the 'git commit' to
abort.
The hook is allowed to edit the message file in place, and can
be used to normalize the message into some project standard
format (if the project has one). It can also be used to refuse
the commit after inspecting the message file.
The hook is allowed to edit the message file in place, and can be used
to normalize the message into some project standard format. It
can also be used to refuse the commit after inspecting the message
file.
The default 'commit-msg' hook, when enabled, detects duplicate
"Signed-off-by" lines, and aborts the commit if one is found.
@ -131,8 +142,8 @@ The default 'commit-msg' hook, when enabled, detects duplicate
post-commit
~~~~~~~~~~~
This hook is invoked by 'git commit'. It takes no
parameter, and is invoked after a commit is made.
This hook is invoked by 'git commit'. It takes no parameters, and is
invoked after a commit is made.
This hook is meant primarily for notification, and cannot affect
the outcome of 'git commit'.
@ -267,9 +278,11 @@ does not know the entire set of branches, so it would end up
firing one e-mail per ref when used naively, though. The
<<post-receive,'post-receive'>> hook is more suited to that.
Another use suggested on the mailing list is to use this hook to
implement access control which is finer grained than the one
based on filesystem group.
In an environment that restricts the users' access only to git
commands over the wire, this hook can be used to implement access
control without relying on filesystem ownership and group
membership. See linkgit:git-shell[1] for how you might use the login
shell to restrict the user's access to only git commands.
Both standard output and standard error output are forwarded to
'git send-pack' on the other end, so you can simply `echo` messages

View File

@ -654,6 +654,7 @@ extern int warn_on_object_refname_ambiguity;
extern const char *apply_default_whitespace;
extern const char *apply_default_ignorewhitespace;
extern const char *git_attributes_file;
extern const char *git_hooks_path;
extern int zlib_compression_level;
extern int core_compression_level;
extern int core_compression_seen;

View File

@ -717,6 +717,9 @@ static int git_default_core_config(const char *var, const char *value)
if (!strcmp(var, "core.attributesfile"))
return git_config_pathname(&git_attributes_file, var, value);
if (!strcmp(var, "core.hookspath"))
return git_config_pathname(&git_hooks_path, var, value);
if (!strcmp(var, "core.bare")) {
is_bare_repository_cfg = git_config_bool(var, value);
return 0;

View File

@ -31,6 +31,7 @@ const char *git_log_output_encoding;
const char *apply_default_whitespace;
const char *apply_default_ignorewhitespace;
const char *git_attributes_file;
const char *git_hooks_path;
int zlib_compression_level = Z_BEST_SPEED;
int core_compression_level;
int core_compression_seen;

View File

@ -825,7 +825,10 @@ const char *find_hook(const char *name)
static struct strbuf path = STRBUF_INIT;
strbuf_reset(&path);
strbuf_git_path(&path, "hooks/%s", name);
if (git_hooks_path)
strbuf_addf(&path, "%s/%s", git_hooks_path, name);
else
strbuf_git_path(&path, "hooks/%s", name);
if (access(path.buf, X_OK) < 0)
return NULL;
return path.buf;

37
t/t1350-config-hooks-path.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/sh
test_description='Test the core.hooksPath configuration variable'
. ./test-lib.sh
test_expect_success 'set up a pre-commit hook in core.hooksPath' '
mkdir -p .git/custom-hooks .git/hooks &&
write_script .git/custom-hooks/pre-commit <<-\EOF &&
echo CUSTOM >>actual
EOF
write_script .git/hooks/pre-commit <<-\EOF
echo NORMAL >>actual
EOF
'
test_expect_success 'Check that various forms of specifying core.hooksPath work' '
test_commit no_custom_hook &&
git config core.hooksPath .git/custom-hooks &&
test_commit have_custom_hook &&
git config core.hooksPath .git/custom-hooks/ &&
test_commit have_custom_hook_trailing_slash &&
git config core.hooksPath "$PWD/.git/custom-hooks" &&
test_commit have_custom_hook_abs_path &&
git config core.hooksPath "$PWD/.git/custom-hooks/" &&
test_commit have_custom_hook_abs_path_trailing_slash &&
cat >expect <<-\EOF &&
NORMAL
CUSTOM
CUSTOM
CUSTOM
CUSTOM
EOF
test_cmp expect actual
'
test_done