Git pre-push крючки - PullRequest
       30

Git pre-push крючки

101 голосов
/ 16 ноября 2010

Я хотел бы запускать юнит-тесты перед каждым нажатием git, и если тесты не пройдены, отмените толчок, но я даже не могу найти хук предварительного толчка, есть только предварительный коммит и предварительный ребаз.

Ответы [ 7 ]

191 голосов
/ 03 февраля 2013

Git получил хук pre-push в выпуске 1.8.2.

Пример сценария pre-push: https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample

1.8.2 в примечаниях к выпуску, рассказывающих о новом предварительном толчкекрючок: https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt

21 голосов
/ 16 ноября 2010

Я бы предпочел запустить тест в pre-commit-hook.Потому что изменение уже зафиксировано при фиксации.Тяните и тяните только обменивайтесь информацией о уже записанных изменениях.Если тест не пройден, у вас уже будет «сломанная» ревизия в вашем хранилищеНажимаете ли вы это или нет.

19 голосов
/ 29 января 2014

Git получил предварительный зацеп в выпуске 1.8.2.

Предварительные 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 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

Как видите, в примере используется защищенная ветвь, являющаяся предметом ловушки предварительного нажатия.

13 голосов
/ 16 ноября 2010

Если вы используете командную строку, самый простой способ сделать это - написать скрипт push, который запускает ваши модульные тесты и, в случае успеха, завершает push.

Edit

Начиная с git 1.8.2 этот ответ устарел.Смотрите ответ manojlds выше.

7 голосов
/ 16 ноября 2010

Для этого нет ловушки, потому что push - это не операция, которая изменяет ваш репозиторий

Вы можете выполнять проверки на принимающей стороне, однако, в хуке post-receive. Вот где вы обычно отклоняете входящий толчок. Выполнение юнит-тестов может быть немного сложным, но это зависит от вас.

5 голосов
/ 17 февраля 2011

Для записи, в Git 1.6 есть патч , который добавляет хук предварительного пуша . Я не знаю, работает ли он против 1.7.

Вместо того, чтобы возиться с этим, вы можете запустить push-скрипт, как рекомендовано @kubi. Вы также можете сделать это заданием Rake, чтобы оно было в вашем репо. ruby-git может помочь с этим. Если вы проверите целевое репо, вы можете запускать тесты только при отправке в производственное репо.

Наконец, вы можете запустить свои тесты в вашем pre-commit хуке, но проверьте, для какой ветки фиксируется. Тогда вы могли бы иметь, скажем, ветвь production, которая требует прохождения всех тестов до принятия коммита, но вашему master это не важно. limerick_rake может быть полезно в этом сценарии.

1 голос
/ 01 октября 2017

Сценарий , связанный ответом с высоким рейтингом , показывает параметры и т.д. для pre-push ловушки ($1 - удаленное имя, $2 URL) и какдоступ к коммитам (строки 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:
#
# $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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...