Hooks are programs you can place in a hooks directory to triggeractions at certain points in git’s execution. Hooks that don’t havethe executable bit set are ignored.
By default the hooks directory is$GIT_DIR/hooks
, but that can bechanged via thecore.hooksPath
configuration variable (seegit-config[1]).
Before Git invokes a hook, it changes its working directory to either$GIT_DIR in a bare repository or the root of the working tree in a non-barerepository. An exception are hooks triggered during a push (pre-receive,update,post-receive,post-update,push-to-checkout) which are alwaysexecuted in $GIT_DIR.
Environment variables, such asGIT_DIR
,GIT_WORK_TREE
, etc., are exportedso that Git commands run by the hook can correctly locate the repository. Ifyour hook needs to invoke Git commands in a foreign repository or in adifferent working tree of the same repository, then it should clear theseenvironment variables so they do not interfere with Git operations at theforeign location. For example:
local_desc=$(git describe)foreign_desc=$(unset $(git rev-parse --local-env-vars); git -C ../foreign-repo describe)
Hooks can get their arguments via the environment, command-linearguments, and stdin. See the documentation for each hook below fordetails.
git init
may copy hooks to the new repository, depending on itsconfiguration. See the "TEMPLATE DIRECTORY" section ingit-init[1] for details. When the rest of this document refersto "default hooks" it’s talking about the default template shippedwith Git.
The currently supported hooks are described below.
This hook is invoked bygit-am[1]. It takes a singleparameter, the name of the file that holds the proposed commitlog message. Exiting with a non-zero status causesgit am
to abortbefore applying the patch.
The hook is allowed to edit the message file in place, and canbe used to normalize the message into some project standardformat. It can also be used to refuse the commit after inspectingthe message file.
The defaultapplypatch-msg hook, when enabled, runs thecommit-msg hook, if the latter is enabled.
This hook is invoked bygit-am[1]. It takes no parameter, and isinvoked after the patch is applied, but before a commit is made.
If it exits with non-zero status, then the working tree will not becommitted after applying the patch.
It can be used to inspect the current working tree and refuse tomake a commit if it does not pass certain tests.
The defaultpre-applypatch hook, when enabled, runs thepre-commit hook, if the latter is enabled.
This hook is invoked bygit-am[1]. It takes no parameter,and is invoked after the patch is applied and a commit is made.
This hook is meant primarily for notification, and cannot affectthe outcome ofgit am
.
This hook is invoked bygit-commit[1], and can be bypassedwith the--no-verify
option. It takes no parameters, and isinvoked before obtaining the proposed commit log message andmaking a commit. Exiting with a non-zero status from this scriptcauses thegit commit
command to abort before creating a commit.
The defaultpre-commit hook, when enabled, catches introductionof lines with trailing whitespaces and aborts the commit whensuch a line is found.
All thegit commit
hooks are invoked with the environmentvariableGIT_EDITOR=:
if the command will not bring up an editorto modify the commit message.
The defaultpre-commit hook, when enabled—and with thehooks.allownonascii
config option unset or set to false—preventsthe use of non-ASCII filenames.
This hook is invoked bygit-merge[1], and can be bypassedwith the--no-verify
option. It takes no parameters, and isinvoked after the merge has been carried out successfully and beforeobtaining the proposed commit log message tomake a commit. Exiting with a non-zero status from this scriptcauses thegit merge
command to abort before creating a commit.
The defaultpre-merge-commit hook, when enabled, runs thepre-commit hook, if the latter is enabled.
This hook is invoked with the environment variableGIT_EDITOR=:
if the command will not bring up an editorto modify the commit message.
If the merge cannot be carried out automatically, the conflictsneed to be resolved and the result committed separately (seegit-merge[1]). At that point, this hook will not be executed,but thepre-commit hook will, if it is enabled.
This hook is invoked bygit-commit[1] right after preparing thedefault log message, and before the editor is started.
It takes one to three parameters. The first is the name of the filethat contains the commit log message. The second is the source of the commitmessage, and can be:message
(if a-m
or-F
option wasgiven);template
(if a-t
option was given or theconfiguration optioncommit.template
is set);merge
(if thecommit is a merge or a.git/MERGE_MSG
file exists);squash
(if a.git/SQUASH_MSG
file exists); orcommit
, followed bya commit object name (if a-c
,-C
or--amend
option was given).
If the exit status is non-zero,git commit
will abort.
The purpose of the hook is to edit the message file in place, andit is not suppressed by the--no-verify
option. A non-zero exitmeans a failure of the hook and aborts the commit. It should notbe used as a replacement for the pre-commit hook.
The sampleprepare-commit-msg
hook that comes with Git removes thehelp message found in the commented portion of the commit template.
This hook is invoked bygit-commit[1] andgit-merge[1], and can bebypassed with the--no-verify
option. It takes a single parameter,the name of the file that holds the proposed commit log message.Exiting with a non-zero status causes the command to abort.
The hook is allowed to edit the message file in place, and can be usedto normalize the message into some project standard format. Itcan also be used to refuse the commit after inspecting the messagefile.
The defaultcommit-msg hook, when enabled, detects duplicateSigned-off-by
trailers, and aborts the commit if one is found.
This hook is invoked bygit-commit[1]. It takes no parameters, and isinvoked after a commit is made.
This hook is meant primarily for notification, and cannot affectthe outcome ofgit commit
.
This hook is called bygit-rebase[1] and can be used to prevent abranch from getting rebased. The hook may be called with one ortwo parameters. The first parameter is the upstream from whichthe series was forked. The second parameter is the branch beingrebased, and is not set when rebasing the current branch.
This hook is invoked when agit-checkout[1] orgit-switch[1] is run after having updated theworktree. The hook is given three parameters: the ref of the previous HEAD,the ref of the new HEAD (which may or may not have changed), and a flagindicating whether the checkout was a branch checkout (changing branches,flag=1) or a file checkout (retrieving a file from the index, flag=0).This hook cannot affect the outcome ofgit switch
orgit checkout
,other than that the hook’s exit status becomes the exit status ofthese two commands.
It is also run aftergit-clone[1], unless the--no-checkout
(-n
) option isused. The first parameter given to the hook is the null-ref, the second theref of the new HEAD and the flag is always 1. Likewise forgit worktree add
unless--no-checkout
is used.
This hook can be used to perform repository validity checks, auto-displaydifferences from the previous HEAD if different, or set working dir metadataproperties.
This hook is invoked bygit-merge[1], which happens when agit pull
is done on a local repository. The hook takes a single parameter, a statusflag specifying whether or not the merge being done was a squash merge.This hook cannot affect the outcome ofgit merge
and is not executed,if the merge failed due to conflicts.
This hook can be used in conjunction with a corresponding pre-commit hook tosave and restore any form of metadata associated with the working tree(e.g.: permissions/ownership, ACLS, etc). See contrib/hooks/setgitperms.perlfor an example of how to do this.
This hook is called bygit-push[1] and can be used to preventa push from taking place. The hook is called with two parameterswhich provide the name and location of the destination remote, if anamed remote is not being used both values will be the same.
Information about what is to be pushed is provided on the hook’s standardinput with lines of the form:
<local-ref> SP <local-object-name> SP <remote-ref> SP <remote-object-name> LF
For instance, if the commandgit push origin master:foreign
were run thehook would receive a line like the following:
refs/heads/master 67890 refs/heads/foreign 12345
although the full object name would be supplied. If the foreign ref does notyet exist the<remote-object-name>
will be the all-zeroes object name. If aref is to be deleted, the<local-ref>
will be supplied as(delete)
and the<local-object-name>
will be the all-zeroes object name. If the local commitwas specified by something other than a name which could be expanded (such asHEAD~
, or an object name) it will be supplied as it was originally given.
If this hook exits with a non-zero status,git push
will abort withoutpushing anything. Information about why the push is rejected may be sentto the user by writing to standard error.
This hook is invoked bygit-receive-pack[1] when it reacts togit push
and updates reference(s) in its repository.Just before starting to update refs on the remote repository, thepre-receive hook is invoked. Its exit status determines the successor failure of the update.
This hook executes once for the receive operation. It takes noarguments, but for each ref to be updated it receives on standardinput a line of the format:
<old-oid> SP <new-oid> SP <ref-name> LF
where<old-oid>
is the old object name stored in the ref,<new-oid>
is the new object name to be stored in the ref and<ref-name>
is the full name of the ref.When creating a new ref,<old-oid>
is the all-zeroes object name.
If the hook exits with non-zero status, none of the refs will beupdated. If the hook exits with zero, updating of individual refs canstill be prevented by theupdate hook.
Both standard output and standard error output are forwarded togit send-pack
on the other end, so you can simplyecho
messagesfor the user.
The number of push options given on the command line ofgit push --push-option=...
can be read from the environmentvariableGIT_PUSH_OPTION_COUNT
, and the options themselves arefound inGIT_PUSH_OPTION_0
,GIT_PUSH_OPTION_1
,…If it is negotiated to not use the push options phase, theenvironment variables will not be set. If the client selectsto use push options, but doesn’t transmit any, the count variablewill be set to zero,GIT_PUSH_OPTION_COUNT=0
.
See the section on "Quarantine Environment" ingit-receive-pack[1] for some caveats.
This hook is invoked bygit-receive-pack[1] when it reacts togit push
and updates reference(s) in its repository.Just before updating the ref on the remote repository, the update hookis invoked. Its exit status determines the success or failure ofthe ref update.
The hook executes once for each ref to be updated, and takesthree parameters:
the name of the ref being updated,
the old object name stored in the ref,
and the new object name to be stored in the ref.
A zero exit from the update hook allows the ref to be updated.Exiting with a non-zero status preventsgit receive-pack
from updating that ref.
This hook can be used to preventforced update on certain refs bymaking sure that the object name is a commit object that is adescendant of the commit object named by the old object name.That is, to enforce a "fast-forward only" policy.
It could also be used to log the old..new status. However, itdoes not know the entire set of branches, so it would end upfiring one e-mail per ref when used naively, though. Thepost-receive hook is more suited to that.
In an environment that restricts the users' access only to gitcommands over the wire, this hook can be used to implement accesscontrol without relying on filesystem ownership and groupmembership. Seegit-shell[1] for how you might use the loginshell to restrict the user’s access to only git commands.
Both standard output and standard error output are forwarded togit send-pack
on the other end, so you can simplyecho
messagesfor the user.
The defaultupdate hook, when enabled—and withhooks.allowunannotated
config option unset or set to false—preventsunannotated tags from being pushed.
This hook is invoked bygit-receive-pack[1]. If the server hasset the multi-valued config variablereceive.procReceiveRefs
, and thecommands sent toreceive-pack have matching reference names, thesecommands will be executed by this hook, instead of by the internalexecute_commands()
function. This hook is responsible for updatingthe relevant references and reporting the results back toreceive-pack.
This hook executes once for the receive operation. It takes noarguments, but uses a pkt-line format protocol to communicate withreceive-pack to read commands, push-options and send results. In thefollowing example for the protocol, the letterS stands forreceive-pack and the letterH stands for this hook.
# Version and features negotiation.S: PKT-LINE(version=1\0push-options atomic...)S: flush-pktH: PKT-LINE(version=1\0push-options...)H: flush-pkt
# Send commands from server to the hook.S: PKT-LINE(<old-oid> <new-oid> <ref>)S: ... ...S: flush-pkt# Send push-options only if the 'push-options' feature is enabled.S: PKT-LINE(push-option)S: ... ...S: flush-pkt
# Receive results from the hook.# OK, run this command successfully.H: PKT-LINE(ok <ref>)# NO, I reject it.H: PKT-LINE(ng <ref> <reason>)# Fall through, let 'receive-pack' execute it.H: PKT-LINE(ok <ref>)H: PKT-LINE(option fall-through)# OK, but has an alternate reference. The alternate reference name# and other status can be given in option directives.H: PKT-LINE(ok <ref>)H: PKT-LINE(option refname <refname>)H: PKT-LINE(option old-oid <old-oid>)H: PKT-LINE(option new-oid <new-oid>)H: PKT-LINE(option forced-update)H: ... ...H: flush-pkt
Each command for theproc-receive hook may point to a pseudo-referenceand always has a zero-old as its old-oid, while theproc-receive hookmay update an alternate reference and the alternate reference may existalready with a non-zero old-oid. For this case, this hook will use"option" directives to report extended attributes for the reference givenby the leading "ok" directive.
The report of the commands of this hook should have the same order asthe input. The exit status of theproc-receive hook only determinesthe success or failure of the group of commands sent to it, unlessatomic push is in use.
This hook is invoked bygit-receive-pack[1] when it reacts togit push
and updates reference(s) in its repository.The hook executes on the remote repository once after all the proposedref updates are processed and if at least one ref is updated as theresult.
The hook takes no arguments. It receives one line on standard input foreach ref that is successfully updated following the same format as thepre-receive hook.
This hook does not affect the outcome ofgit receive-pack
, as itis called after the real work is done.
This supersedes thepost-update hook in that it getsboth old and new values of all the refs in addition to theirnames.
Both standard output and standard error output are forwarded togit send-pack
on the other end, so you can simplyecho
messagesfor the user.
The defaultpost-receive hook is empty, but there isa sample scriptpost-receive-email
provided in thecontrib/hooks
directory in Git distribution, which implements sending commitemails.
The number of push options given on the command line ofgit push --push-option=...
can be read from the environmentvariableGIT_PUSH_OPTION_COUNT
, and the options themselves arefound inGIT_PUSH_OPTION_0
,GIT_PUSH_OPTION_1
,…If it is negotiated to not use the push options phase, theenvironment variables will not be set. If the client selectsto use push options, but doesn’t transmit any, the count variablewill be set to zero,GIT_PUSH_OPTION_COUNT=0
.
See the "post-receive" section ingit-receive-pack[1] foradditional details.
This hook is invoked bygit-receive-pack[1] when it reacts togit push
and updates reference(s) in its repository.It executes on the remote repository once after all the refs havebeen updated.
It takes a variable number of parameters, each of which is thename of ref that was actually updated.
This hook is meant primarily for notification, and cannot affectthe outcome ofgit receive-pack
.
Thepost-update hook can tell what are the heads that were pushed,but it does not know what their original and updated values are,so it is a poor place to do log old..new. Thepost-receive hook does get both original andupdated values of the refs. You might consider it instead if you needthem.
When enabled, the defaultpost-update hook runsgit update-server-info
to keep the information used by dumbtransports (e.g., HTTP) up to date. If you are publishinga Git repository that is accessible via HTTP, you shouldprobably enable this hook.
Both standard output and standard error output are forwarded togit send-pack
on the other end, so you can simplyecho
messagesfor the user.
This hook is invoked by any Git command that performs referenceupdates. It executes whenever a reference transaction is prepared,committed or aborted and may thus get called multiple times. The hookalso supports symbolic reference updates.
The hook takes exactly one argument, which is the current state thegiven reference transaction is in:
"prepared": All reference updates have been queued to thetransaction and references were locked on disk.
"committed": The reference transaction was committed and allreferences now have their respective new value.
"aborted": The reference transaction was aborted, no changeswere performed and the locks have been released.
For each reference update that was added to the transaction, the hookreceives on standard input a line of the format:
<old-value> SP <new-value> SP <ref-name> LF
where<old-value>
is the old object name passed into the referencetransaction,<new-value>
is the new object name to be stored in theref and<ref-name>
is the full name of the ref. When force updatingthe reference regardless of its current value or when the reference isto be created anew,<old-value>
is the all-zeroes object name. Todistinguish these cases, you can inspect the current value of<ref-name>
viagit rev-parse
.
For symbolic reference updates the<old_value>
and<new-value>
fields could denote references instead of objects. A reference will bedenoted with aref: prefix, likeref:<ref-target>
.
The exit status of the hook is ignored for any state except for the"prepared" state. In the "prepared" state, a non-zero exit status willcause the transaction to be aborted. The hook will not be called with"aborted" state in that case.
This hook is invoked bygit-receive-pack[1] when it reacts togit push
and updates reference(s) in its repository, and whenthe push tries to update the branch that is currently checked outand thereceive.denyCurrentBranch
configuration variable is set toupdateInstead
. Such a push by default is refused if the workingtree and the index of the remote repository has any difference fromthe currently checked out commit; when both the working tree and theindex match the current commit, they are updated to match the newlypushed tip of the branch. This hook is to be used to override thedefault behaviour.
The hook receives the commit with which the tip of the currentbranch is going to be updated. It can exit with a non-zero statusto refuse the push (when it does so, it must not modify the index orthe working tree). Or it can make any necessary changes to theworking tree and to the index to bring them to the desired statewhen the tip of the current branch is updated to the new commit, andexit with a zero status.
For example, the hook can simply rungit read-tree -u -m HEAD "$1"
in order to emulategit fetch
that is run in the reverse directionwithgit push
, as the two-tree form ofgit read-tree -u -m
isessentially the same asgit switch
orgit checkout
that switches branches whilekeeping the local changes in the working tree that do not interferewith the difference between the branches.
This hook is invoked bygit gc --auto
(seegit-gc[1]). Ittakes no parameter, and exiting with non-zero status from this scriptcauses thegit gc --auto
to abort.
This hook is invoked by commands that rewrite commits(git-commit[1] when called with--amend
andgit-rebase[1]; however, full-history (re)writing tools likegit-fast-import[1] orgit-filter-repo typicallydo not call it!). Its first argument denotes the command it wasinvoked by: currently one ofamend
orrebase
. Furthercommand-dependent arguments may be passed in the future.
The hook receives a list of the rewritten commits on stdin, in theformat
<old-object-name> SP <new-object-name> [ SP <extra-info> ] LF
Theextra-info is again command-dependent. If it is empty, thepreceding SP is also omitted. Currently, no commands pass anyextra-info.
The hook always runs after the automatic note copying (see"notes.rewrite.<command>" ingit-config[1]) has happened, andthus has access to these notes.
The following command-specific comments apply:
This hook is invoked bygit-send-email[1].
It takes these command line arguments. They are,1. the name of the file which holds the contents of the email to be sent.2. The name of the file which holds the SMTP headers of the email.
The SMTP headers are passed in the exact same way as they are passed to theuser’s Mail Transport Agent (MTA). In effect, the email given to the user’sMTA, is the contents of $2 followed by the contents of $1.
An example of a few common headers is shown below. Take notice of thecapitalization and multi-line tab structure.
From: Example <from@example.com>To: to@example.comCc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.comSubject: PATCH-STRING
Exiting with a non-zero status causesgit send-email
to abortbefore sending any e-mails.
The following environment variables are set when executing the hook.
GIT_SENDEMAIL_FILE_COUNTER
A 1-based counter incremented by one for every file holding an e-mailto be sent (excluding any FIFOs). This counter does not follow thepatch series counter scheme. It will always start at 1 and will end atGIT_SENDEMAIL_FILE_TOTAL.
GIT_SENDEMAIL_FILE_TOTAL
The total number of files that will be sent (excluding any FIFOs). Thiscounter does not follow the patch series counter scheme. It will alwaysbe equal to the number of files being sent, whether there is a coverletter or not.
These variables may for instance be used to validate patch series.
The samplesendemail-validate
hook that comes with Git checks that all sentpatches (excluding the cover letter) can be applied on top of the upstreamrepository default branch without conflicts. Some placeholders are left foradditional validation steps to be performed after all patches of a given serieshave been applied.
This hook is invoked when the configuration optioncore.fsmonitor
isset to.git/hooks/fsmonitor-watchman
or.git/hooks/fsmonitor-watchmanv2
depending on the version of the hook to use.
Version 1 takes two arguments, a version (1) and the time in elapsednanoseconds since midnight, January 1, 1970.
Version 2 takes two arguments, a version (2) and a token that is usedfor identifying changes since the token. For watchman this would bea clock id. This version must output to stdout the new token followedby a NUL before the list of files.
The hook should output to stdout the list of all files in the workingdirectory that may have changed since the requested time. The logicshould be inclusive so that it does not miss any potential changes.The paths should be relative to the root of the working directoryand be separated by a single NUL.
It is OK to include files which have not actually changed. All changesincluding newly-created and deleted files should be included. Whenfiles are renamed, both the old and the new name should be included.
Git will limit what files it checks for changes as well as whichdirectories are checked for untracked files based on the path namesgiven.
An optimized way to tell git "all files have changed" is to returnthe filename/
.
The exit status determines whether git will use the data from thehook to limit its search. On error, it will fall back to verifyingall files and folders.
This hook is invoked bygit-p4 submit
.
Thep4-changelist
hook is executed after the changelistmessage has been edited by the user. It can be bypassed with the--no-verify
option. It takes a single parameter, the nameof the file that holds the proposed changelist text. Exitingwith a non-zero status causes the command to abort.
The hook is allowed to edit the changelist file and can be usedto normalize the text into some project standard format. It canalso be used to refuse the Submit after inspect the message file.
Rungit-p4 submit --help
for details.
This hook is invoked bygit-p4 submit
.
Thep4-prepare-changelist
hook is executed right after preparingthe default changelist message and before the editor is started.It takes one parameter, the name of the file that contains thechangelist text. Exiting with a non-zero status from the scriptwill abort the process.
The purpose of the hook is to edit the message file in place,and it is not suppressed by the--no-verify
option. This hookis called even if--prepare-p4-only
is set.
Rungit-p4 submit --help
for details.
This hook is invoked bygit-p4 submit
.
Thep4-post-changelist
hook is invoked after the submit hassuccessfully occurred in P4. It takes no parameters and is meantprimarily for notification and cannot affect the outcome of thegit p4 submit action.
Rungit-p4 submit --help
for details.
This hook is invoked bygit-p4 submit
. It takes no parameters and nothingfrom standard input. Exiting with non-zero status from this script preventgit-p4 submit
from launching. It can be bypassed with the--no-verify
command line option. Rungit-p4 submit --help
for details.
This hook is invoked when the index is written in read-cache.cdo_write_locked_index.
The first parameter passed to the hook is the indicator for theworking directory being updated. "1" meaning working directorywas updated or "0" when the working directory was not updated.
The second parameter passed to the hook is the indicator for whetheror not the index was updated and the skip-worktree bit could havechanged. "1" meaning skip-worktree bits could have been updatedand "0" meaning they were not.
Only one parameter should be set to "1" when the hook runs. The hookrunning passing "1", "1" should not be possible.
Part of thegit[1] suite