Накладіть гачки попереднього натискання


115

Я хотів би виконати одиничні тести перед кожним натисканням git, і якщо тести не вдаються, скасуйте натискання, але я навіть не можу знайти гачок попереднього натискання, є лише попередня фіксація та попередня перезавантаження.


Відповіді:


14

Я б скоріше запустив тест у попередній зачіпці. Тому що зміни вже фіксуються при здійсненні. Натисніть і витягніть лише обмін інформацією про вже записану зміну. Якщо тест не вдасться, у вашому сховищі вже буде "зламана" версія. Ви натискаєте на це чи ні.


203
Я, як правило, погоджуюся, хоча якщо ви звикли робити багато додаткових зобов'язань пізніше, а тестовий набір великий, це може бути недоцільним.
Каскабель

Я бачу. Тому я б запропонував тести виконати перед об'єднанням з основною гілкою, але немає і гака попереднього об'єднання. Однак є "гачок" оновлення, який можна використовувати для запобігання оновлення реф у віддаленому сховищі: "Незадовго до оновлення реф на віддаленому сховищі виклик гака оновлення. Його статус виходу визначає успіх або невдачу реф. Гак виконується один раз для кожного оновлення, який повинен бути оновлений, і приймає три параметри: ім'я оновлення, яке оновлюється, старе ім'я об'єкта, яке зберігається в реф.
ordnungswidrig

18
Даун проголосував, оскільки - хоча інформаційний - повністю ігнорує питання ОП.
Дембінський

1
@TheDembinski Я б не сказав, що він ігнорує питання щодо ОП. Насправді він враховує це і говорить про те, що є кращий спосіб зробити це, ніж той, що мали на увазі ОП. Це взагалі така відповідь, яку я хотів би отримати.
calder.ty

9
@ calder.ty - Ні. manojlds краще вирішує те, що має значення. Насправді гачки попереднього введення, які виконують тести, як правило, погана ідея. Це передбачає, що всі речі, які будуть вчинені, повинні пройти тести. Що погано для загальних робочих потоків, орієнтованих на співпрацю. Так що ... я не згоден; це не кращий спосіб зробити "це", а також не вирішує питання.
Дембінський

209

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
@manojlds Ви знаєте, для чого призначений цей гачок? Я хотів би використовувати його, щоб підштовхувати бінарний файл до своїх клієнтів при натисканні на певну гілку (тобто будувати нічну версію та завантажувати її з завитком, перш ніж натискати). Проблема полягає в тому, що збирання та завантаження потребує певного часу, а віддалене з'єднання закриває. Таким чином, я закінчую свою вбудовану та завантажену бінарну інформацію для клієнтів, але не підштовхую до репо, оскільки віддалене репо закриває з'єднання. Будь-яка ідея, як обійти це? А може це погана ідея в його корені.
ігрик

@igrek Ви знайшли рішення з питанням про закриття з'єднання?
Маріо Естрада

1
@MarioEstrada, так, я не пам’ятаю точно, як, але я змусив його натиснути двічі: спочатку команда git запускає одиничні тести, а потім, якщо вона не відключається, вона натискає і запускає інший натиск в інший потік, якщо перший час натискання вихід, другий з іншого потоку працює для мене. Якщо або перший, і другий успішні, тоді перший натискання змінюється, а другий нічого не штовхає. Хитрість полягає в тому, що у мене був доданий аргумент, який обходить одиничні тести (який використовувався для другого натискання git, тому він не запускав одиничні тести знову)
ігри

24

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

Як ви бачите, у прикладі використовується захищена гілка, що підлягає гачку перед натисканням.


14

Якщо ви використовуєте командний рядок, найпростіший спосіб зробити це - написати push-скрипт, який запускає ваші одиничні тести, і, якщо вони досягли успіху, завершує натиск.

Редагувати

Станом на git 1.8.2 ця відповідь застаріла. Дивіться відповідь манольдса вище.


ти маєш на увазі взагалі не використання гачків? просто замініть "git pull" на, наприклад, "git uinttestspull"? це не зовсім те, що мені потрібно
овець вовк

1
@sheepwalker: s / pull / push /, і використовувати псевдонім, щоб зробити його приємним і коротким.
Каскабель

@sheepwalker Так, це не саме те, про що ви просили, але, як сказав @calmh, немає жодних попередніх натискань.
кубі

8

Для цього немає гачка, тому що push не є операцією, яка модифікує ваше сховище.

Ви можете робити перевірки на приймальній стороні, хоча, на post-receiveгачку. Саме там ви зазвичай відхиляєте вхідний поштовх. Виконання тестів на одиниці може бути трохи інтенсивним, але це залежить від вас.


6

Для запису є патч до Git 1.6, який додає гачок перед натисканням . Я не знаю, чи працює це проти 1.7.

Замість того, щоб возитися з цим, ви можете запустити push-сценарій, як @kubi рекомендується. Ви також можете зробити це завдання Rake замість цього, щоб це було у вашому репо. ruby-git може допомогти у цьому. Якщо ви перевіряєте цільове репо, ви можете запускати тести лише під час натискання на виробниче репо.

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


дякую, насправді я вже обрав останній варіант (Нарешті, ви можете запустити свої тести у вашому гачку, який попередньо здійснив ..)
Овчанка

1

Скрипт пов'язує високо-голосування відповісти показує параметри і т.д. на pre-pushгак ( $1це ім'я віддаленого, $2URL) , і як отримати доступ до фіксацій (рядки 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.