|
NAME | SYNOPSIS | DESCRIPTION | SUBCOMMANDS | OPTIONS | WRAPPERS | CONFIGURATION | SEE ALSO | GIT | COLOPHON |
|
|
|
GIT-HOOK(1) Git Manual GIT-HOOK(1)
git-hook - Run git hooks
git hook run [--allow-unknown-hook-name] [--ignore-missing] [--to-stdin=<path>] [(-j|--jobs) <n>]
<hook-name> [-- <hook-args>]
git hook list [--allow-unknown-hook-name] [-z] [--show-scope] <hook-name>
A command interface for running git hooks (see githooks(5)), for
use by other scripted git commands.
This command parses the default configuration files for sets of
configs like so:
[hook "linter"]
event = pre-commit
command = ~/bin/linter --cpp20
In this example, [hook "linter"] represents one script -
~/bin/linter --cpp20 - which can be shared by many repos, and even
by many hook events, if appropriate.
To add an unrelated hook which runs on a different event, for
example a spell-checker for your commit messages, you would write
a configuration like so:
[hook "linter"]
event = pre-commit
command = ~/bin/linter --cpp20
[hook "spellcheck"]
event = commit-msg
command = ~/bin/spellchecker
With this config, when you run git commit, first ~/bin/linter
--cpp20 will have a chance to check your files to be committed
(during the pre-commit hook event`), and then ~/bin/spellchecker
will have a chance to check your commit message (during the
commit-msg hook event).
Commands are run in the order Git encounters their associated
hook.<friendly-name>.event configs during the configuration parse
(see git-config(1)). Although multiple hook.linter.event configs
can be added, only one hook.linter.command event is valid - Git
uses "last-one-wins" to determine which command to run.
So if you wanted your linter to run when you commit as well as
when you push, you would configure it like so:
[hook "linter"]
event = pre-commit
event = pre-push
command = ~/bin/linter --cpp20
With this config, ~/bin/linter --cpp20 would be run by Git before
a commit is generated (during pre-commit) as well as before a push
is performed (during pre-push).
And if you wanted to run your linter as well as a secret-leak
detector during only the "pre-commit" hook event, you would
configure it instead like so:
[hook "linter"]
event = pre-commit
command = ~/bin/linter --cpp20
[hook "no-leaks"]
event = pre-commit
command = ~/bin/leak-detector
With this config, before a commit is generated (during
pre-commit), Git would first start ~/bin/linter --cpp20 and second
start ~/bin/leak-detector. It would evaluate the output of each
when deciding whether to proceed with the commit.
For a full list of hook events which you can set your
hook.<friendly-name>.event to, and how hooks are invoked during
those events, see githooks(5).
Git will ignore any hook.<friendly-name>.event that specifies an
event it doesn’t recognize. This is intended so that tools which
wrap Git can use the hook infrastructure to run their own hooks;
see "WRAPPERS" for more guidance.
In general, when instructions suggest adding a script to
.git/hooks/<hook-event>, you can specify it in the config instead
by running:
git config set hook.<some-name>.command <path-to-script>
git config set --append hook.<some-name>.event <hook-event>
This way you can share the script between multiple repos. That is,
cp ~/my-script.sh ~/project/.git/hooks/pre-commit would become:
git config set hook.my-script.command ~/my-script.sh
git config set --append hook.my-script.event pre-commit
run
Runs hooks configured for <hook-name>, in the order they are
discovered during the config parse. The default <hook-name>
from the hookdir is run last. See githooks(5) for supported
hook names.
Any positional arguments to the hook should be passed after a
mandatory -- (or --end-of-options, see gitcli(7)). See
githooks(5) for arguments hooks might expect (if any).
list [-z] [--show-scope]
Print a list of hooks which will be run on <hook-name> event.
If no hooks are configured for that event, print a warning and
return 1. Use -z to terminate output lines with NUL instead of
newlines.
--allow-unknown-hook-name
By default git hook run and git hook list will bail out when
<hook-name> is not a hook event known to Git (see githooks(5)
for the list of known hooks). This is meant to help catch
typos such as prereceive when pre-receive was intended. Pass
this flag to allow unknown hook names.
--to-stdin
For "run"; specify a file which will be streamed into the
hook’s stdin. The hook will receive the entire file from
beginning to EOF.
--ignore-missing
Ignore any missing hook by quietly returning zero. Used for
tools that want to do a blind one-shot run of a hook that may
or may not be present.
-z
Terminate "list" output lines with NUL instead of newlines.
--show-scope
For "list"; prefix each configured hook’s friendly name with a
tab-separated config scope (e.g. local, global, system),
mirroring the output style of git config --show-scope.
Traditional hooks from the hookdir are unaffected.
-j, --jobs
Only valid for run.
Specify how many hooks to run simultaneously. If this flag is
not specified, the value of the hook.jobs config is used, see
git-config(1). If neither is specified, defaults to 1 (serial
execution).
When greater than 1, it overrides the per-hook
hook.<friendly-name>.parallel setting, allowing all hooks for
the event to run concurrently, even if they are not
individually marked as parallel.
Some hooks always run sequentially regardless of this flag or
the hook.jobs config, because git knows they cannot safely run
in parallel: applypatch-msg, pre-commit, prepare-commit-msg,
commit-msg, post-commit, post-checkout, and push-to-checkout.
git hook run has been designed to make it easy for tools which
wrap Git to configure and execute hooks using the Git hook
infrastructure. It is possible to provide arguments and stdin via
the command line, as well as specifying parallel or series
execution if the user has provided multiple hooks.
Assuming your wrapper wants to support a hook named
"mywrapper-start-tests", you can have your users specify their
hooks like so:
[hook "setup-test-dashboard"]
event = mywrapper-start-tests
command = ~/mywrapper/setup-dashboard.py --tap
Then, in your mywrapper tool, you can invoke any users' configured
hooks by running:
git hook run --allow-unknown-hook-name mywrapper-start-tests \
# providing something to stdin
--stdin some-tempfile-123 \
# execute multiple hooks in parallel
--jobs 3 \
# plus some arguments of your own...
-- \
--testname bar \
baz
Take care to name your wrapper’s hook events in a way which is
unlikely to overlap with Git’s native hooks (see githooks(5)) - a
hook event named ‘mywrappertool-validate-commit` is much less
likely to be added to native Git than a hook event named
validate-commit. If Git begins to use a hook event named the same
thing as your wrapper hook, it may invoke your users’ hooks in
unintended and unsupported ways.
hook.<friendly-name>.command
The command to execute for hook.<friendly-name>.
<friendly-name> is a unique name that identifies this hook.
The hook events that trigger the command are configured with
hook.<friendly-name>.event. The value can be an executable
path or a shell oneliner. If more than one value is specified
for the same <friendly-name>, only the last value parsed is
used. See git-hook(1).
hook.<friendly-name>.event
The hook events that trigger hook.<friendly-name>. The value
is the name of a hook event, like "pre-commit" or "update".
(See githooks(5) for a complete list of hook events.) On the
specified event, the associated hook.<friendly-name>.command
is executed. This is a multi-valued key. To run
hook.<friendly-name> on multiple events, specify the key more
than once. An empty value resets the list of events, clearing
any previously defined events for hook.<friendly-name>. See
git-hook(1).
The <friendly-name> must not be the same as a known hook event
name (e.g. do not use hook.pre-commit.event). Using a known
event name as a friendly-name is a fatal error because it
creates an ambiguity with hook.<event>.enabled and
hook.<event>.jobs. For unknown event names, a warning is
issued when <friendly-name> matches the event value.
hook.<friendly-name>.enabled
Whether the hook hook.<friendly-name> is enabled. Defaults to
true. Set to false to disable the hook without removing its
configuration. This is particularly useful when a hook is
defined in a system or global config file and needs to be
disabled for a specific repository. See git-hook(1).
hook.<friendly-name>.parallel
Whether the hook hook.<friendly-name> may run in parallel with
other hooks for the same event. Defaults to false. Set to true
only when the hook script is safe to run concurrently with
other hooks for the same event. If any hook for an event does
not have this set to true, all hooks for that event run
sequentially regardless of hook.jobs. Only configured (named)
hooks need to declare this. Traditional hooks found in the
hooks directory do not need to, and run in parallel when the
effective job count is greater than 1. See git-hook(1).
hook.<event>.enabled
Switch to enable or disable all hooks for the <event> hook
event. When set to false, no hooks fire for that event,
regardless of any per-hook hook.<friendly-name>.enabled
settings. Defaults to true. See git-hook(1).
Note on naming: <event> must be the event name (e.g.
pre-commit), not a hook friendly-name. Since using a known
event name as a friendly-name is disallowed (see
hook.<friendly-name>.event above), there is no ambiguity
between event-level and per-hook .enabled settings for known
events. For unknown events, if a friendly-name matches the
event name despite the warning, .enabled is treated as
per-hook only.
hook.<event>.jobs
Specifies how many hooks can be run simultaneously for the
<event> hook event (e.g. hook.post-receive.jobs = 4).
Overrides hook.jobs for this specific event. The same
parallelism restrictions apply: this setting has no effect
unless all configured hooks for the event have
hook.<friendly-name>.parallel set to true. Set to -1 to use
the number of available CPU cores. Must be a positive integer
or -1; zero is rejected with a warning. See git-hook(1).
Note on naming: although this key resembles
hook.<friendly-name>.* (a per-hook setting), <event> must be
the event name, not a hook friendly name. The key component is
stored literally and looked up by event name at runtime with
no translation between the two namespaces. A key like
hook.my-hook.jobs is stored under "my-hook" but the lookup at
runtime uses the event name (e.g. "post-receive"), so
hook.my-hook.jobs is silently ignored even when my-hook is
registered for that event. Use hook.post-receive.jobs or any
other valid event name when setting hook.<event>.jobs.
hook.jobs
Specifies how many hooks can be run simultaneously during
parallelized hook execution. If unspecified, defaults to 1
(serial execution). Set to -1 to use the number of available
CPU cores. Can be overridden on a per-event basis with
hook.<event>.jobs. Some hooks always run sequentially
regardless of this setting because they operate on shared data
and cannot safely be parallelized:
applypatch-msg, prepare-commit-msg, commit-msg
Receive a commit message file and may rewrite it in place.
pre-commit, post-checkout, push-to-checkout, post-commit
Access the working tree, index, or repository state.
This setting has no effect unless all configured hooks for the
event have hook.<friendly-name>.parallel set to true.
For pre-push hooks, which normally keep stdout and stderr
separate, setting this to a value greater than 1 (or passing
-j) will merge stdout into stderr to allow correct
de-interleaving of parallel output.
githooks(5)
Part of the git(1) suite
This page is part of the git (Git distributed version control
system) project. Information about the project can be found at
⟨http://git-scm.com/⟩. If you have a bug report for this manual
page, see ⟨http://git-scm.com/community⟩. This page was obtained
from the project's upstream Git repository
⟨https://github.com/git/git.git⟩ on 2026-05-24. (At that time,
the date of the most recent commit that was found in the
repository was 2026-05-22.) If you discover any rendering
problems in this HTML version of the page, or you believe there is
a better or more up-to-date source for the page, or you have
corrections or improvements to the information in this COLOPHON
(which is not part of the original manual page), send a mail to
man-pages@man7.org
Git 2.54.0.254.g6a4418 2026-05-22 GIT-HOOK(1)
Pages that refer to this page: git(1), git-hook(1), githooks(5)