Git
Chapters ▾ 2nd Edition

8.3 Настройване на Git - Git Hooks

Git Hooks

Както повечето VCS системи, Git разполага с механизъм да изпълнява потребителски скриптове при възникване на определни събития. Тези скриптове са известни като Hooks (обработчици на събития) и се разделят на две групи: client-side и server-side. Клиентските hooks се пускат при операции като къмитване или сливане, докато сървърните отразяват събития от мрежови операции като например получаване на публикувани къмити. Можете да използвате hooks за всякакви неща.

Инсталиране на Hook

Всички hooks се съхраняват в hooks поддиректория в Git директорията. В повечето проекти това е .git/hooks. Когато инициализирате ново хранилище с git init, Git попълва въпросната директория с множество примерни скриптове, които освен че са полезни сами по себе си, също така и документират входните стойности за всеки скрипт. Всички примери са написани като шел скриптове с малко Perl, но всъщност кои да е коректно именувани и изпълними скриптове ще работят добре — можете да ги пишете на Ruby или Python или който език предпочитате. Ако искате да използвате фабрично доставените с Git скриптове, ще трябва да преименувате файловете, те завършват на .sample.

За да разрешите hook скрипт, поставете коректно именуван (без разширение) и изпълним файл в hooks поддиректорията на .git. От този момент натам, той би трябвало да се изпълнява. Ще разгледаме няколко от основните имена за hooks файлове.

Клиентски Hooks

Налични са много client-side hooks. Тази секция ги разделя в категориите committing-workflow hooks, email-workflow скриптове и всичко останало.

Note

Важно е да споменем, че клиентските hooks не се копират, когато клонирате хранилище. Ако целта на скриптовете ви е да наложите дадена политика на работа, вероятно ще искате да правите това на сървъра, вижте примера в Примерна Git-Enforced политика.

Committing-Workflow Hooks

Първите четири hooks се занимават с процеса на къмитване.

Скриптът pre-commit се пуска първи, още преди да напишете къмит съобщението. Той се използва за проверка на snapshot-а, който ще бъде къмитнат и следи дали не сте забравили нещо, дали се изпълняват тестове и т.н. Ако изходният код от този hook не е нулев (успешно завършен), то къмитът ще бъде отказан, въпреки че това е преодолимо с git commit --no-verify. Можете да правите неща като проверка на стила на писане на код (чрез изпълнение на lint или нещо от рода), проверка за празни символи в края на редовете (подразбиращият се hook върши именно това), или проверка за подходяща документация на нови методи в кода.

Следва prepare-commit-msg hook-ът, който се стартира преди текстовия редактор, но след създаването на къмит съобщението по подразбиране. Това ви позволява да редактирате съобщението преди автора на къмита да го види на екрана. Този hook има няколко аргумента: пътя на файла, който съхранява къмит съобщението, типа на къмита и SHA-1 стойността, ако това е amended къмит. Това не е кой знае колко полезен Hook за нормални къмити, вместо това е приложим за такива, в които съобщението по подразбиране се генерира автоматично — като templated къмит съобщенията, сливащите къмити, а също и squashed и amended къмитите. Можете да го използвате в комбинация с commit template за да вмъквате информация програмно.

Hook-ът commit-msg приема един параметър, който отново е път към временен файл, съдържащ къмит съобщението от разработчика. Ако скриптът завърши неуспешно Git отказва къмит процеса, така че можете да го използвате за валидиране на статуса на проекта или на самото къмит съобщение преди да позволите на къмита да мине. В последната част от главата ще видим как да ползваме този hook за да проверим дали подадено къмит съобщение отговаря на определени правила.

След като целият къмит процес завърши се стартира post-commit hook-а. Той не приема параметри, но можете лесно да видите последния къмит с git log -1 HEAD. Общо взето, този hook се използва за нотификации или подобни процеси.

Email Workflow Hooks

Можете да настроите три client-side hooks за имейл базирани работни процеси. Всички те се стартират през командата git am, така че ако не я използвате, може да прескочите направо към следващата част в главата. Ако обаче получавате пачове през имейл, изготвени с git format-patch, тогава някой от тези скриптове може да ви е от полза.

Първият изпълнен е applypatch-msg. Той приема един аргумент: името на временния файл с къмит съобщението. Git отказва пача, ако скриптът завърши с код за неуспех. Бихте могли да го използвате за да се уверите, че къмит съобщението е правилно форматирано или да го нормализирате с допълнителна редакция.

Следващият hook, който се изпълнява при прилагане на пачове с git am е pre-applypatch. Противно на очакваното предвид името му, той се изпълнява след прилагането на пача, но преди да е направен къмит, така че би могъл да се използва за инспектиране на snapshot-а преди къмитване. С този скрипт можете да пускате тестове в работната директория. Ако нещо липсва или тестовете не минават, кодът за неуспех прекратява git am и пачът не се прилага.

Последният hook касаещ git am операцията е post-applypatch, който се пуска след къмитване. Можете да го използвате за да нотифицирате група хора или автора на пача, че сте го приложили. С този скрипт не можете да спрете patching процеса.

Други Client Hooks

pre-rebase hook-ът се изпълнява преди пребазирането на каквото и да било и може да прекрати процеса при код за неуспех. Може да се използва например за забрана на пребазиране на публикувани в отдалечени хранилища къмити. Примерният pre-rebase hook, който Git инсталира прави това, въпреки че използва някои презумпции, които може да не отговарят на конкретния ви работен процес.

Hook-ът post-rewrite се изпълнява от команди, които заместват къмити като git commit --amend и git rebase (макар и не от git filter-branch). Единичният параметър, който получава, е командата направила заместването ведно със списък от промените на stdin. Този hook може да се ползва за повечето неща, за които могат и post-checkout и post-merge.

След успешно изпълнение на команда git checkout, post-checkout hook-ът се стартира и бихте могли да го използвате за настройка на работната директория за специфичните изисквания на проекта например. Това може да означава преместване на големи двоични файлове, които не искате да проследявате, автоматично генериране на документация и т.н.

Hook-ът post-merge се пуска след успешна merge команда. Може да се използва за възстановяване на информация, която Git не проследява — като например права върху файлове. Също така би могъл да се използва за проверка за наличето на външни за Git файлове, които бихте желали да се копират в проекта, когато работната директория се промени.

Hook-ът pre-push работи по време на git push, след като отдалечените референции се обновят, но преди трансфера на каквито и да било обекти. Той получава в параметри името и адреса на отдалечените хранилища и списъка на референциите, които ще бъдат обновени през stdin. Може да се използва за валидация на набор от промени преди push операцията (код за неуспех на скрипта отменя публикуването).

Git редовно извършва garbage collection действия като част от нормалната си работа извиквайки git gc --auto. Съответно, hook-ът pre-auto-gc се изпълнява преди процеса по почистването и може да ви известява, че то предстои да се направи или пък да го отмени, ако моментът не е подходящ за това.

Сървърни Hooks

В допълнение към клиентските hooks, ако сте системен администратор, можете да използвате множество важни сървърни такива за да прилагате почти всеки вид политика за вашия проект. Тези скриптове се изпълняват преди и след публикувания на промени в сървъра. Тези, които работят преди приемане на публикуването могат да върнат код за неуспех по всяко време и да го откажат, както и да отпечатат съобщение за грешка към клиента. Така че можете да си създадете push политика колкото сложна, колкото ви е нужно.

pre-receive

Първият изпълняван скрипт по време на обработка на push от клиент е pre-receive. Той приема от stdin списък на референциите, които се публикуват и ако излезе с код за неуспех никоя от тях не се приема. Може да ползвате този hook за да проверявате, че никоя от променените референции не е non-fast-forward или да правите контрол на достъп за всички референции и файлове, които ще бъдат променени от публикуването.

update

Скриптът update е много подобен на pre-receive, разликата е, че се изпълнява по веднъж за всеки клон, който публикуващият се опитва да обнови. Ако се обновяват няколко клона, pre-receive стартира само веднъж, докато update върви за всеки клон. Вместо да чете от стандартния вход, този скрипт приема три параметъра: името на референцията (клона), SHA-1 стойността, към която референцията е сочела преди push операцията, и SHA-1 стойността, която потребителят опитва да изпрати. Ако update скриптът завърши с код за неуспех, то само текущата референция се отказва, другите все още могат да бъдат обновени.

post-receive

Накрая, post-receive hook-ът се изпълнява след края на целия процес и може да се използва за обновяване на други услуги или нотифициране на потребители. Той получава същите stdin данни както и pre-receive. Сред примерните негови приложения биха могли да са разпращане на имейли до потребители, нотифициране на continuous integration сървър или ъпдейт на ticket-tracking система — можете дори да парсвате къмит съобщения, за да проверявате дали дадени тикети трябва да се отворят, редактират или затворят. Скриптът не може да спре push процеса, но връзката с клиента не се прекъсва докато той не завърши, така че бъдете внимателни, ако се опитвате да правите с него неща отнемащи прекалено дълго време.