I would like to run a unit-tests before every git push and if tests fails, cancel the push, but I can\'t even find pre-push hook, there is pre-commit and pre-rebase only.
Git got the pre-push
hook in the 1.8.2
release.
Sample pre-push
script: https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample
1.8.2 release notes talking about the new pre-push hook: https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt
I would rather run the test in a pre-commit-hook. Because the change is already recorded when committing. Push and pull only exchange information about already recorded changed. If a test fails you would already have a "broken" revision in your repository. Whether you're pushing it or not.
For the record, there is a patch to Git 1.6 that adds a pre-push hook. I don't know whether it works against 1.7.
Rather than mess with that, you could run push script like @kubi recommended. You could also make it a Rake task instead so it's in your repo. ruby-git could help with this. If you check the target repo, you could run tests only when pushing to the production repo.
Finally, you could run your tests in your pre-commit
hook but check for what branch is being committed to. Then you could have a, say, a production
branch that requires all tests pass before accepting a commit but your master
doesn't care. limerick_rake may be useful in that scenario.
There isn't a hook for it, because a push isn't an operation that modifies your repository.
You can do the checks on the receiving side though, in the post-receive
hook. That is where you would usually reject an incoming push. Running unit tests might be a little intensive to do in a hook, but that's up to you.
Git got the pre-push hook in the 1.8.2 release.
Pre-push hooks are what I needed along with pre-commit hooks. Apart from protecting a branch, they can also provide extra security combined with pre-commit hooks.
And for an example on how to use (taken and adopted and enhanced from this nice entry)
Simple example to login to vagrant, run tests and then push
#!/bin/bash
# Run the following command in the root of your project to install this pre-push hook:
# cp git-hooks/pre-push .git/hooks/pre-push; chmod 700 .git/hooks/pre-push
CMD="ssh vagrant@192.168.33.10 -i ~/.vagrant.d/insecure_private_key 'cd /vagrant/tests; /vagrant/vendor/bin/phpunit'"
protected_branch='master'
# Check if we actually have commits to push
commits=`git log @{u}..`
if [ -z "$commits" ]; then
exit 0
fi
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
if [[ $current_branch = $protected_branch ]]; then
eval $CMD
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo "failed $CMD"
exit 1
fi
fi
exit 0
As you can see the example uses a protected branch, subject of the pre-push hook.
The script linked by the highly-voted answer shows the parameters etc to the pre-push hook ($1
is remote name, $2
URL) and how to access the commits (lines read
from stdin have structure <local ref> <local sha1> <remote ref> <remote sha1>
)
#!/bin/sh
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local sha1> <remote ref> <remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]
then
# Handle delete
:
else
if [ "$remote_sha" = $z40 ]
then
# New branch, examine all commits
range="$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
# Check for WIP commit
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
if [ -n "$commit" ]
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0