Git предварительные пусковые крючки

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

Ответ 1

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

Ответ 3

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

Предварительные пусковые крючки - это то, что мне нужно, и крючки с предварительной фиксацией. Помимо защиты ветки, они также могут обеспечить дополнительную безопасность в сочетании с крючками предварительной фиксации.

И для примера о том, как использовать (взятый и принятый и улучшенный из этой приятной записи)

Простой пример входа в бродягу, запуск тестов, а затем нажмите

#!/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,.*/\(.*\),\1,')

if [[ $current_branch = $protected_branch ]]; then
    eval $CMD
    RESULT=$?
    if [ $RESULT -ne 0 ]; then
        echo "failed $CMD"
        exit 1
    fi
fi
exit 0

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

Ответ 4

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

Edit

Как и в случае с git 1.8.2, этот ответ устарел. См. Manojlds выше.

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

script, связанный с высоким голосованием показывает параметры и т.д. pre-push hook ($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