Ответы:
Я бы предпочел запустить тест в режиме предварительной фиксации. Потому что изменение уже записано при фиксации. Push and pull только обмениваются информацией об уже записанных изменениях. Если тест не пройден, в вашем репозитории уже будет «сломанная» ревизия. Настаиваете вы на это или нет.
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
В версии 1.8.2 Git получил хук предварительного нажатия.
Перехватчики pre-push - это то, что мне нужно вместе с перехватчиками pre-commit. Помимо защиты ветки, они также могут обеспечить дополнительную безопасность в сочетании с перехватчиками перед фиксацией.
И для примера того, как использовать (взято, адаптировано и улучшено из этой хорошей записи )
Простой пример входа в 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
Как вы можете видеть, в примере используется защищенная ветка, являющаяся объектом хука pre-push.
Если вы используете командную строку, самый простой способ сделать это - написать сценарий push, который запускает ваши модульные тесты и, в случае успеха, завершает отправку.
редактировать
Начиная с git 1.8.2 этот ответ устарел. См. Ответ Manojlds выше.
Для этого нет ловушки, потому что push - это не операция, которая изменяет ваш репозиторий.
Однако вы можете делать проверки на принимающей стороне, в post-receive
крюке. Именно здесь вы обычно отклоняете входящий push. Выполнение модульных тестов в ловушке может быть немного сложным, но это зависит от вас.
Для записи, есть патч к Git 1.6, который добавляет ловушку pre-push . Не знаю, работает ли против 1.7.
Вместо того, чтобы возиться с этим, вы можете запустить push-скрипт, как рекомендовано @kubi. Вы также можете сделать это задачей Rake, чтобы она была в вашем репо. ruby-git может в этом помочь. Если вы проверите целевое репо, вы можете запускать тесты только при отправке в производственное репо.
Наконец, вы можете запускать тесты в своем pre-commit
хуке, но проверять, к какой ветке привязаны. Тогда у вас может быть, скажем, production
ветка, которая требует, чтобы все тесты прошли перед принятием фиксации, но вам master
все равно. limerick_rake может быть полезен в этом сценарии.
Скрипт связывает высоко-голосование ответить показывает параметры и т.д. на pre-push
крюк ( $1
это имя удаленного, $2
URL) , и как получить доступ к фиксаций (строки read
из стандартного ввода имеют структуру <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