I've looked at the githooks manpage but unless I'm missing something I don't see an option for local, post-push git hooks. I'd like to have one that updates the api docs on my web server (for which I already have a script) after I push the master branch to the GitHub repo. Of course I could just write my own script that combines the git push and the api docs run, but that feels somewhat inelegant.
-
the `post-update` hooks can be triggered for this case right? – Agnibha Jan 30 '19 at 08:21
7 Answers
Another solution to this problem is to have a wrapper for git push
that executes .git/hooks/pre-push
and .git/hooks/post-push
scripts before and after the git push
call. A possible wrapper could look like this:
#!/bin/sh
GIT_DIR_="$(git rev-parse --git-dir)"
BRANCH="$(git rev-parse --symbolic --abbrev-ref $(git symbolic-ref HEAD))"
PRE_PUSH="$GIT_DIR_/hooks/pre-push"
POST_PUSH="$GIT_DIR_/hooks/post-push"
test -x "$PRE_PUSH" &&
exec "$PRE_PUSH" "$BRANCH" "$@"
git push "$@"
test $? -eq 0 && test -x "$POST_PUSH" &&
exec "$POST_PUSH" "$BRANCH" "$@"
Saved as git-push-wh
somewhere in your PATH
, it can then be called as git push-wh
if you want to push with hooks.

- 4,725
- 2
- 28
- 47
-
3This is brilliant... I use separate remotes: one where I host my code, a bare repo in my production server so I added [this code](https://gist.github.com/SaifurRahmanMohsin/0a6d1944cbd7815e58e7) to my [~/.functions.sh](https://github.com/mathiasbynens/dotfiles) and use ** push origin ** ** push production ** it automatically launches the website (since that’s defined in push-post) in my browser once the push completes. Thanks! – Saifur Rahman Mohsin Sep 24 '15 at 22:55
-
Current code does not work in git worktrees, to fix it, just change 3 lines: ` GIT_DIR_="$(git rev-parse --git-path hooks)" PRE_PUSH="${GIT_DIR_}/pre-push" POST_PUSH="${GIT_DIR_}/post-push" ` – KaszpiR Jun 12 '19 at 16:21
I recently came across the same issue. I wanted a hook so that a push from my git submodule would commit the new submodule reference in the 'superproject'.
As Chris mentioned, the best way is to just use a git alias, like this:
$ git config alias.xpush '!git push $1 $2 && update-server.sh'
# (remember the backslash before the ! if your shell requires it)
This adds the following to your .git/config file:
[alias]
xpush = !git push $1 $2 && update-server.sh
And so now, if you type:
$ git xpush
your changes will be pushed, and then update-server.sh will be executed.

- 25,241
- 18
- 52
- 63

- 13,513
- 3
- 56
- 85
-
3Umm what about if you are in a branch? and you do that xpush? shouldn't be something like !git push $1 $2 && update-server.sh so you can specify origin branch? – Jlbelmonte Nov 11 '11 at 20:53
-
Note that overriding an existing command is not possible with a git alias, see https://stackoverflow.com/questions/3538774/is-it-possible-to-override-git-command-by-git-alias – brillout Oct 08 '18 at 19:14
This type of hook is not supported by Git. It falls outside the valid reasons for a Git hook as given by Git's maintainer.
The introductory remark in the above linked message speaks almost directly to your case:
I do not particularly like hooks that act after an operation is initiated locally and act solely on local data. This is maybe because I still consider git tools building blocks suitable for higher level scripting more than other people do.
P.S. A “Single Push” Hint
- There are too many caveats for a full explanation, but if you can figure it all out you should be able to deal with the details.
An extra pushurl
to a local repo with an “alternates” objects store could give you a low overhead way to locally execute a push hook. But really, the effort is much more than git push upstream && update-web-server
(maybe in a shell alias, git alias, or script).

- 99,403
- 23
- 97
- 120

- 214,407
- 26
- 209
- 186
-
3Same information can be found in: http://permalink.gmane.org/gmane.comp.version-control.git/71069 – Jakub Narębski Nov 25 '09 at 21:24
-
2Please, notice that from 1.8.2 Git added a **pre-push** hook. Check my answer to find more information. – Adrián Deccico Nov 27 '13 at 04:47
From Git 1.8.2 there is a new hook invoked before the push operation: pre-push If the script returns other than 0 the push operation will be cancelled.
Mention in the release notes: https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt#L167

- 4,975
- 2
- 22
- 30
-
50I don't thing this answer is the good one, it tells about the pre-push hook, and the original question was about post-push hook. – Levente Holló Oct 20 '16 at 10:39
-
4Levente Holló,the pre-push hook is executed after the user runs `git-push` and before git actually pushes the commit/s.There is no other push related hook integrated in Git. – Adrián Deccico Oct 20 '16 at 23:39
Implementing a post-push hook is in fact possible by using the reference-transaction
hook. After a push is done, git will locally update the remote tracking branch, triggering a reference transaction on refs/remotes/REMOTE/BRANCH
.
Here's an example for a hook that uses this technique:
#!/bin/bash
set -eu
while read oldvalue newvalue refname
do
if [ $1 = committed -a $refname = refs/remotes/origin/main ]
then
exec .git/hooks/post-push
fi
done
This script must have the executable bit and be placed in .git/hooks/reference-transaction
. The hook runs after pushing the main branch to origin. Put your actual hook script in .git/hooks/post-push
.

- 3,089
- 2
- 18
- 22

- 2,446
- 2
- 16
- 20
-
Perfect! To me, this should be be the ✅ accepted answer! I just put my own command on the line where it says `exec .git/hooks/post-push` instead of creating another file. Push to deploy via remote ssh command: Achieved. Thanks! – gigawatt Jun 27 '23 at 16:23
I'm using a function for this:
current_branch() {
local ref=$(git symbolic-ref HEAD 2> /dev/null) || return
echo ${ref#refs/heads/}
}
gp() {
local post_push="$(git rev-parse --git-dir)/hooks/post-push"
git push "$@" && {
[[ -x "$post_push" ]] && "$post_push" "$(current_branch)" "$@"
}
}
compdef _git gp=git-push
The compdef part is for ZSH.

- 93
- 1
- 6
Just create a pre-push
hook with a sleep at the top. Ensure sleep is long enough for the commits to be uploaded to upstream server based on your network connection speed. Ideally add a &
to run your script in the background:
(sleep 30 && .git/hooks/post-push) &

- 769
- 8
- 17