Git 预推钩子

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4196148/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 09:29:56  来源:igfitidea点击:

Git pre-push hooks

githook

提问by sheepwalker

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 push 之前运行单元测试,如果测试失败,取消推送,但我什至找不到 pre-push 钩子,只有 pre-commit 和 pre-rebase。

采纳答案by ordnungswidrig

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.

我宁愿在预提交挂钩中运行测试。因为提交时已经记录了更改。推拉仅交换有关已记录更改的信息。如果测试失败,您的存储库中就已经有一个“损坏的”修订版。不管你推不推。

回答by manojlds

Git got the pre-pushhook in the 1.8.2release.

Gitpre-push1.8.2发布中获得了 钩子。

Sample pre-pushscript: https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample

示例pre-push脚本: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

1.8.2 发行说明谈论新的 pre-push hook:https: //github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt

回答by Jimmy Kane

Git got the pre-push hook in the 1.8.2 release.

Git 在 1.8.2 版本中获得了 pre-push hook。

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

登录 vagrant,运行测试然后推送的简单示例

#!/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 [email protected] -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,.*/\(.*\),,')

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.

如您所见,该示例使用受保护的分支,即 pre-push 钩子的主题。

回答by kubi

If you are using the command line, the easiest way to do this is to write a push script that runs your unit tests and, if they succeed, completes the push.

如果您使用命令行,最简单的方法是编写一个运行单元测试的推送脚本,如果它们成功,则完成推送。

Edit

编辑

As of git 1.8.2 this answer is outdated. See manojlds's answer above.

从 git 1.8.2 开始,这个答案已经过时了。请参阅上面的 manojlds 的回答。

回答by Jakob Borg

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-receivehook. 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.

不过,您可以在接收方的post-receive挂钩中进行检查。这就是您通常会拒绝传入推送的地方。在钩子中运行单元测试可能有点密集,但这取决于您。

回答by Turadg

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.

作为记录,Git 1.6有一个补丁添加了一个 pre-push hook。我不知道它是否适用于 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-gitcould help with this. If you check the target repo, you could run tests only when pushing to the production repo.

您可以像@kubi 推荐的那样运行推送脚本,而不是搞砸。你也可以把它变成一个 Rake 任务,所以它在你的仓库中。ruby-git可以帮助解决这个问题。如果您检查目标存储库,则只能在推送到生产存储库时运行测试。

Finally, you could run your tests in your pre-commithook but check for what branch is being committed to. Then you could have a, say, a productionbranch that requires all tests pass before accepting a commit but your masterdoesn't care. limerick_rakemay be useful in that scenario.

最后,您可以在您的pre-commit钩子中运行您的测试,但检查正在提交的分支。然后你可以有一个production分支,它需要在接受提交之前通过所有测试,但你master并不关心。在这种情况下,limerick_rake可能很有用。

回答by serv-inc

The script linked by the highly-voted answershows the parameters etc to the pre-pushhook($1is remote name, $2URL) and how to access the commits (lines readfrom stdin have structure <local ref> <local sha1> <remote ref> <remote sha1>)

高票答案链接脚本显示了pre-push钩子的参数等($1是远程名称、$2URL)以及如何访问提交(read来自 stdin 的行具有结构<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:
#
#  -- Name of the remote to which the push is being done
#  -- 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=""
url=""

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