git-hook(1) — Linux manual page

NAME | SYNOPSIS | DESCRIPTION | SUBCOMMANDS | OPTIONS | WRAPPERS | CONFIGURATION | SEE ALSO | GIT | COLOPHON

GIT-HOOK(1)                     Git Manual                    GIT-HOOK(1)

NAME         top

       git-hook - Run git hooks

SYNOPSIS         top

       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>

DESCRIPTION         top

       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

SUBCOMMANDS         top

       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.

OPTIONS         top

       --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.

WRAPPERS         top

       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.

CONFIGURATION         top

       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.

SEE ALSO         top

       githooks(5)

GIT         top

       Part of the git(1) suite

COLOPHON         top

       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)