Git pre-push hooks

前端 未结 7 1253
慢半拍i
慢半拍i 2020-11-28 02:47

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.

相关标签:
7条回答
  • 2020-11-28 03:13

    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

    0 讨论(0)
  • 2020-11-28 03:16

    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.

    0 讨论(0)
  • 2020-11-28 03:24

    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.

    0 讨论(0)
  • 2020-11-28 03:28

    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.

    0 讨论(0)
  • 2020-11-28 03:29

    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.

    0 讨论(0)
  • 2020-11-28 03:29

    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
    
    0 讨论(0)
提交回复
热议问题