If the script .git/hooks/pre-push exists and is executable it will be called before a `git push` command, and when the script exits with a non-zero status the push will be aborted. The hook can be overridden by passing the '--no-verify' option to `git push`. The pre-push hook is usefull to run tests etc. before push. Or to make sure that if a binary solution like git-media, git-annex or git-bin is used the binaries are uploaded before the push, so when others do a fetch the binaries will be available already. This also reduces the need for introducing extra (git) commands to e.g. sync binaries. Signed-off-by: Aske Olsson <askeolsson@xxxxxxxxx> --- Documentation/git-push.txt | 11 +++- Documentation/githooks.txt | 12 +++++ builtin/push.c | 6 +++ t/t5542-pre-push-hook.sh | 132 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 t/t5542-pre-push-hook.sh diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index fe46c42..5807b6a 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -11,7 +11,7 @@ SYNOPSIS [verse] 'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [--prune] [-v | --verbose] [-u | --set-upstream] - [<repository> [<refspec>...]] + [ --no-verify] [<repository> [<refspec>...]] DESCRIPTION ----------- @@ -157,6 +157,10 @@ useful if you write an alias or script around 'git push'. receiver share many of the same objects in common. The default is \--thin. +--no-verify:: + This option bypasses the pre-push hook. + See also linkgit:githooks[5]. + -q:: --quiet:: Suppress all output, including the listing of updated refs, @@ -430,6 +434,11 @@ Commits A and B would no longer belong to a branch with a symbolic name, and so would be unreachable. As such, these commits would be removed by a `git gc` command on the origin repository. +HOOKS +----- +This command can run the `pre-push` hook. See linkgit:githooks[5] for +more information. + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index b9003fe..847e0f8 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -176,6 +176,18 @@ save and restore any form of metadata associated with the working tree (eg: permissions/ownership, ACLS, etc). See contrib/hooks/setgitperms.perl for an example of how to do this. +[[pre-push]] +pre-push +~~~~~~~~ + +This hook is invoked by 'git push' and can be bypassed with the +`--no-verify` option. It takes no parameter, and is invoked before +the push happens. +Exiting with a non-zero status from this script causes 'git push' +to abort. + + + [[pre-receive]] pre-receive ~~~~~~~~~~~ diff --git a/builtin/push.c b/builtin/push.c index db9ba30..9c4d2ec 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -16,6 +16,7 @@ static const char * const push_usage[] = { }; static int thin; +static int no_verify; static int deleterefs; static const char *receivepack; static int verbosity; @@ -392,6 +393,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) N_("control recursive pushing of submodules"), PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOLEAN( 0 , "thin", &thin, N_("use thin pack")), + OPT_BOOLEAN('0', "no-verify", &no_verify, "bypass pre-push hook"), OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")), OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")), OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"), @@ -419,6 +421,10 @@ int cmd_push(int argc, const char **argv, const char *prefix) set_refspecs(argv + 1, argc - 1); } + if (!no_verify && run_hook(NULL, "pre-push")) { + die(_("pre-push hook failed: exiting\n")); + } + rc = do_push(repo, flags); if (rc == -1) usage_with_options(push_usage, options); diff --git a/t/t5542-pre-push-hook.sh b/t/t5542-pre-push-hook.sh new file mode 100644 index 0000000..842aa23 --- /dev/null +++ b/t/t5542-pre-push-hook.sh @@ -0,0 +1,132 @@ +#!/bin/sh + +test_description='pre-push hook' + +. ./test-lib.sh + +D=`pwd` +HOOK="master/.git/hooks/pre-push" + +# Repo pair +mk_repo_pair () { + rm -rf master mirror && + mkdir mirror && + ( + cd mirror && + git init && + git config receive.denyCurrentBranch warn + ) + mkdir master && + ( + cd master && + git init && + git remote add $1 up ../mirror + ) +} + +# hook that always succeeds +mk_hook_exec () { +cat > "$HOOK" <<EOF +#!/bin/sh +exit 0 +EOF +chmod +x "$HOOK" +} + +# hook that fails +mk_hook_fail () { +cat > "$HOOK" <<EOF +#!/bin/sh +exit 1 +EOF +chmod +x "$HOOK" +} + +# nonexecutable hook +mk_hook_no_exec () { +rm -f "$HOOK" +cat > "$HOOK" <<EOF +#!/bin/sh +echo 'test run' +exit 0 +EOF +} + +test_expect_success 'push with no pre-push hook' ' + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git push --mirror up + ) +' + +test_expect_success 'push --no-verify with no pre-push hook' ' + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git push --no-verify --mirror up + ) +' + +test_expect_success 'push with succeeding pre-push hook' ' + mk_repo_pair && + ( + mk_hook_exec && + cd master && + echo one >foo && git add foo && git commit -m one && + git push --mirror up + ) +' + +test_expect_success 'push --no-verify with succeeding pre-push hook' ' + mk_repo_pair && + ( + mk_hook_exec && + cd master && + echo one >foo && git add foo && git commit -m one && + git push --no-verify --mirror up + ) +' + +test_expect_success 'push with failing pre-push hook' ' + mk_repo_pair && + ( + mk_hook_fail && + cd master && + echo one >foo && git add foo && git commit -m one && + test_must_fail git push --mirror up + ) +' + +test_expect_success 'push --no-verify with failing hook' ' + mk_repo_pair && + ( + mk_hook_fail && + cd master && + echo one >foo && git add foo && git commit -m one && + git push --no-verify --mirror up + ) +' + +test_expect_success 'push with non-executable pre-push hook' ' + mk_repo_pair && + ( + mk_hook_no_exec && + cd master && + echo one >foo && git add foo && git commit -m one && + git push --mirror up + ) +' + +test_expect_success 'push --no-verify with non-executable pre-push hook' ' + mk_repo_pair && + ( + mk_hook_no_exec && + cd master && + echo one >foo && git add foo && git commit -m one && + git push --no-verify --mirror up + ) +' +test_done -- 1.8.0 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html