Git hoeft niet complex te zijn, maar er zijn bepaalde facetten die ingewikkeld zijn en waar je toch wat energie in moet steken om te begrijpen – Git hooks zijn daar een voorbeeld van. Dit zijn scripts die Git automatisch uitvoert op basis van bepaalde gebeurtenissen.

Hoewel ze eenvoudig kunnen zijn, heb je veel meer mogelijkheden om ze op een effectieve manier te gebruiken. Maar om dit te doen, moet je alle radertjes begrijpen die het hele wiel vormen.

In dit artikel zullen we kijken naar geavanceerde technieken voor Git hooks, waaronder een aantal basisprincipes, hoe je ze kunt maken en installeren, en meer.

In dit artikel zullen we hookparameters en omgevingsvariabelen uitleggen, wat tips en trucs geven, methodes om problemen op te lossen doornemen, en nog veel meer.

De grondbeginselen van Git hooks: een inleiding

Een van de belangrijkste eigenschappen van Git zijn de hooks: een krachtig mechanisme waarmee je taken kunt automatiseren, standaarden kunt afdwingen en consistente werkwijzen kunt garanderen gedurende de levenscyclus van een project.

Git hooks zijn scripts die automatisch worden uitgevoerd op specifieke punten in de Git workflow. Je kunt ze gebruiken om het gedrag van Git aan te passen en uit te breiden om aan de behoeften van je project te voldoen. Hooks zorgen ervoor dat de kwaliteit van de code behouden blijft, tests worden uitgevoerd en implementaties soepel verlopen.

Git biedt verschillende soorten hooks, en elke zal op verschillende momenten in de Git workflow geactiveerd worden:

  • Pre-commit. Deze hooks worden uitgevoerd voordat je een commit afrondt, waardoor je code stijlen kunt afdwingen, tests kunt uitvoeren of op syntax fouten kunt controleren.
  • Post-commit. Dit wordt uitgevoerd nadat je een commit hebt gemaakt. Het is handig voor notificaties of loggen.
  • Pre-push. Deze hook wordt uitgevoerd voordat je code pusht en stelt je in staat om integratietests uit te voeren, te controleren op compatibiliteit of om de kwaliteit te waarborgen.
  • Post-push. De laatste hook wordt uitgevoerd nadat je een push hebt voltooid. Als zodanig is het waardevol voor het uitrollen van code naar productie of het bijwerken van documentatie.

Je vindt hooks in de .git/hooks map van je Git repository. Er zijn daar ook voorbeeldhooks – je kunt ze gebruiken als templates om je eigen custom scripts te maken. De hooks hebben betrekking op een reeks acties en gebruiken een sample- achtervoegsel als referentie:

Een macOS Finder-scherm met een lokale map met 13 witte voorbeeld hooks-bestanden op een grijze achtergrond.
Een lokale Git map met voorbeeld hooks bestanden.

Hooks worden geactiveerd tijdens verschillende Git acties. Bijvoorbeeld, een pre-commit hook start als je wijzigingen commit, en een pre-push hook start voordat je naar remote pusht. Als je meer begrijpt over deze triggers, kun je hooks strategischer inzetten om kwaliteitscontrole te verbeteren en je workflow te stroomlijnen.

Zo maak en installeer je custom Git hooks

Het maken en installeren van basis aangepaste Git hooks kan een complex proces zijn. Maar de basis die je hier zult leren, zal je later voorbereiden op het ontwikkelen van geavanceerde hooks. Laten we een paar concepten doornemen die van toepassing zijn op elke hook die je maakt en installeert.

Een geschikt type hook kiezen

Het gebruik van het juiste hook type voor jouw specifieke use case is een belangrijke eerste stap. Het begint met het begrijpen van je eigen ontwikkelworkflow en behoeften. Hier is een snelle checklist met overwegingen die je mee kan nemen:

  • Overweeg eerst de verschillende fasen van je proces, zoals coderen, testen en deployen. Ga ook na waar dat proces baat zou kunnen hebben bij automatisering en controles.
  • Zoek van daaruit naar plekken in je workflow waar vaak fouten of inconsistenties voorkomen. Custom Git hooks kunnen hierbij helpen. Bijvoorbeeld, als je vergeet om tests uit te voeren voor een commit, kan een pre-commit hook het probleem aanpakken.
  • Vervolgens moet je bedenken wanneer je de hook wilt uitvoeren binnen je werkstroom. Bijvoorbeeld, als je er zeker van wilt zijn dat alle commits voldoen aan de coderingsstandaarden, dan is een pre-commit hook geschikt. Als je code wilt valideren voordat je naar remote pusht, dan is een pre-push hook meer geschikt.
  • Zorg er tenslotte voor dat het gekozen hook type compatibel is met je ontwikkelomgeving en de tools die je gebruikt. Denk na over de scripttaal die je gaat gebruiken voor de hook en zijn uitvoeringsomgeving.

Op dit punt zou je in staat moeten zijn om duidelijke doelen voor je hook te definiëren. Het kan zelfs zijn dat elke doelstelling een ander type hook vereist. Hoewel het verleidelijk is om scripts te maken voor elk mogelijk scenario, is het een goed idee om je eerst te richten op het aanpakken van kritieke pijnpunten.

Custom Git hooks benoemen en plaatsen

Het correct benoemen en plaatsen van aangepaste Git hooks is cruciaal om hun functionaliteit en onderhoudbaarheid te garanderen. Net als met bijvoorbeeld de functies, bestanden, klassenamen  van je code, zouden je Git hooks ook consistente en beschrijvende namen moeten hebben.

Als hooks in de loop van de tijd meerdere projecten zullen ondersteunen, als een template, dan wil je misschien voorvoegsels gebruiken – misschien met initialen van developers, een afdeling of een bedrijfsnaam. Over het algemeen gebruiken Git hooks kleine letters en koppeltekens voor de leesbaarheid – bijvoorbeeld, mijn-project-pre-commit.

Bovendien, hoewel je Git hooks in de .git/hooks map van je repo kunt opslaan, zouden custom hooks in een aparte map in de hoofdmap van het project moeten gaan. Dit voorkomt per ongeluk overschrijven tijdens een Git update. Je wil echter versiebeheer voor die hooks willen gebruiken, samen met de rest van de code van je project.

Een basic custom Git hook maken

De typische manier om een basic Git hook te schrijven is om een nieuw bestand te maken met de naam van je gekozen hook (zoals pre-commit) in je hooks map. We zullen de hook namen later noemen als we het over parameters hebben.

Voordat je een bestand opent om ermee te werken, moet je er zeker van zijn dat het uitvoerbaar is met het volgende commandline fragment:

chmod +x path/to/file/hook-name

Vergeet niet om onze placeholders te vervangen door de juiste informatie. We zullen dit fragment door het hele artikel heen gebruiken, omdat het een typische actie zou moeten zijn als je een nieuwe Git hook aanmaakt.

Zodra het bestand uitvoerbaar en open is, kun je je eigen logica toevoegen met de scripttaal van je voorkeur. Dit kan Bash, Python, Ruby of een andere zijn. Het maken hiervan valt natuurlijk buiten het bereik van wat we hier zullen behandelen. Er zijn later echter enkele pseudocode voorbeelden om specifieke gebruikssituaties en scenario’s te laten zien.

Tot slot, voordat je wijzigingen commit, test je je hook door te proberen de gerelateerde actie uit te voeren (zoals een commit). Dit is de basisaanpak voor het maken van Git hooks, maar er zijn genoeg geavanceerde gebruikssituaties. Daar zullen we het volgende over hebben.

Geavanceerde custom hooks maken en installeren

Het maken van basis Git hooks zal iets zijn dat je veel doet gedurende je carrière als developer. Er zijn echter genoeg situaties die vragen om meer geavanceerde en complexe hooks. Hierna zullen we kijken naar een aantal use cases en voorbeeld hooks voor een aantal veel voorkomende scenario’s.

Een hook maken die code styling afdwingt met linters

Het gebruik van een linter om code styling af te dwingen is een fantastische toepassing voor Git hooks. Het kan helpen om consistente codekwaliteit in je repository te behouden en het zou iets moeten zijn waar je veel waarde uit kunt halen.

Natuurlijk moet je een linter kiezen die past bij de programmeertaal van je project. Black is bijvoorbeeld fantastisch voor Python. Wij gaan hier ESLint voor JavaScript gebruiken om een pre-commit hook te maken.

Installeer eerst de linter als globaal of lokaal pakket binnen je project. Hiervoor heb je Node.js en npm nodig:

npm install eslint --save-dev

Navigeer vervolgens naar je hooks directory binnen je repo. Maak je pre-commit bestand aan en schrijf dan een script dat de linter uitvoert op je opgevoerde bestanden. De hook zou de commit moeten voorkomen als de linter problemen vindt. Hier is een simpel voorbeeld:

#!/bin/sh

# Stash unstaged changes (optional but recommended)
git stash -q --keep-index

# Run the linter on staged files
npm run lint # Replace with the appropriate linting command
LINT_RESULT=$?

# Unstash the stashed changes (optional but recommended)
git stash pop -q

# Exit with the linter's exit code
exit $LINT_RESULT

Zodra je er zeker van bent dat de hook uitvoerbaar is, test hem dan uit door middel van een commit. De pre-commit hook zou de linter moeten uitvoeren. Als er code stijl schendingen zijn, dan zul je de commit niet kunnen voltooien totdat je de problemen opgelost hebt.

Natuurlijk moet je een hook schrijven die werkt met je eigen programmeertaal en linter, in overeenstemming met je project. Je zou dit voorbeeld bijvoorbeeld kunnen uitbreiden met linter configuratie-instellingen, integratie met je bouwproces en meer.

Een hook gebruiken voor het uitvoeren van testen voor een commit

Het implementeren van een pre-commit hook om tests uit te voeren voor een commit is een uitstekende manier om potentiële problemen in een vroeg stadium op te vangen. Op deze manier kun je ervoor zorgen dat je alleen betrouwbare code commit.

Voor dit voorbeeld gebruiken we het Jest test framework voor JavaScript. Je zult iets willen installeren dat geschikt is voor jouw project (zoals altijd):

npm install jest --save-dev

Zoals met elke hook, navigeer je naar je hooks directory, maak je een nieuw bestand aan, geef je het een naam en maak je het uitvoerbaar. Schrijf vanaf hier een script dat tests uitvoert op alle opgevoerde bestanden voor de commit. Hier is een ruwe template:

#!/bin/sh

# Stash unstaged changes (optional but recommended)
git stash -q --keep-index

# Run tests on staged files
npm test # Replace with the appropriate test command
TEST_RESULT=$?

# Unstash the stashed changes (optional but recommended)
git stash pop -q

# Exit with the test's exit code
exit $TEST_RESULT

Wanneer je wijzigingen probeert te committen, zal de hook je tests uitvoeren op de opgevoerde bestanden. De commit zal stoppen voor alle mislukte tests, en je moet de problemen aanpakken voordat je opnieuw commit.

Een hook ontwikkelen voor het automatiseren van versiebeheer en labelen

Een uitstekende manier om het releaseproces te stroomlijnen is het automatiseren van versiebeheer en taggen binnen Git. Dit zorgt voor consistente versiebeheer in je codebase.

Om te beginnen moet je een versiebeheerschema kiezen dat geschikt is voor je project. Dit valt buiten het bereik van dit artikel, maar veel voorkomende schema’s zijn Semantic Versioning (SemVer) of een custom versiebeheerpatroon.

Bepaal vervolgens wat je hook precies gaat doen. Het zou bijvoorbeeld de huidige versie kunnen lezen, deze verhogen volgens een gekozen schema en de benodigde bestanden bijwerken met de nieuwe versie. Je zult ook een script willen schrijven voor het maken van tags gebaseerd op de versie, dat Git commando’s gebruikt om lichtgewicht of geannoteerde tags te maken.

Als je eenmaal je bestand hebt gemaakt en de rechten hebt ingesteld, kun je beginnen met het schrijven van je hook. Dit kan een complexe en zeer specifieke hook zijn, die zelfs van project tot project kan veranderen. De meeste hooks van dit type zullen echter het volgende bevatten:

  • Een functie die een gespecificeerd deel van een versie string (bijvoorbeeld 1.2.3) verhoogt en de nieuwe versie teruggeeft.
  • De mogelijkheid om de huidige versie uit een specifiek versiebestand te lezen.
  • Een functie om het nieuwe versienummer te berekenen, inclusief welk specifiek deel te verhogen. Bijvoorbeeld 0 voor major, 1 voor minor, 2 voor patch.

Vanaf hier moet het script het versiebestand bijwerken met het nieuwe nummer, een lichtgewicht tag aanmaken met de nieuwe versie en optioneel de nieuwe tag naar een remote repository pushen. Zodra je wijzigingen vastlegt, zal de hook ervoor zorgen dat iedere vastlegging wordt geassocieerd met een juiste versie en tag.

Je zult deze hook waarschijnlijk nog verder willen aanpassen aan de eisen van je project. Je zou bijvoorbeeld zaken als het aanmaken van initiële tags, het omgaan met versieconflicten en het updaten van versieverwijzingen in bestanden kunnen afhandelen.

Hook parameters en omgevingsvariabelen begrijpen

Een van de redenen dat Git hooks zo krachtig zijn, is de manier waarop ze omgaan met dynamische variabelen. Het kan echter een complex concept zijn om te begrijpen. Hierna zullen we zowel omgevingsvariabelen als hookparameters bekijken – te beginnen met de laatste.

Hoe parameters aan hooks worden doorgegeven

Hooks kunnen specifieke parameters van Git ontvangen om toegang te krijgen tot contextuele informatie van je hoofdcodebase. Git stelt automatisch parameters in tijdens run-time, en hoewel je ze meestal niet specifiek hoeft te definiëren, moet je ze misschien wel declaren. Het is essentieel om deze te begrijpen om effectieve hooks te ontwikkelen.

Hier is een overzicht van de belangrijkste punten over hookparameters:

  • Git hooks gebruiken positionele variabelen, waarbij $1 verwijst naar de eerste parameter, $2 naar de tweede parameter, enzovoort. Deze parameters zijn niet willekeurig; ze hebben specifieke betekenissen en doelen. Als zodanig, hoewel ze niet ‘officieel’ zijn, vertegenwoordigen ze geaccepteerde conventies bij het benaderen van de waarden van parameters.
  • De volgorde van de parameters volgt een specifiek patroon. Git geeft deze parameters door aan je hookscript in een vooraf bepaalde volgorde, gebaseerd op de context van het hook-event.
  • De namen van de variabelen geven het algemene doel van de parameters weer. Bijvoorbeeld, $1 bevat vaak het pad naar een bestand, terwijl $2 de bron van een actie kan zijn.

Als je een parameter zou toevoegen die de hook niet kan aanroepen, zou het script deze over het algemeen niet kunnen gebruiken. Parameters zijn specifiek voor een bepaalde hook en uitvoeringscontext. Om problemen te voorkomen, moet je alleen gedocumenteerde parameters gebruiken. Je kunt echter de waarde van een positionele parameter toewijzen aan een andere variabele en deze vervolgens gebruiken in je script:

#!/bin/sh

# Assign $1 to the variable EXAMPLE
EXAMPLE=$1

# Use EXAMPLE variable
echo "The commit message file is: $EXAMPLE"

In dit geval zal de variabele EXAMPLE dezelfde waarde hebben als $1, wat het pad is naar het bestand van het commit-bericht. Het gebruik van de gedocumenteerde variabelenamen maakt je code echter begrijpelijker.

Merk op dat je in sommige gevallen standard input (stdin ) zult gebruiken om parameters te definiëren, in welk geval je die elementen in je hooks moet verwerken.

Git hook parameter waarden en definities vinden

Omdat elke Git hook zijn eigen parameters heeft, zul je waarschijnlijk een referentie nodig hebben om te achterhalen wat ze zijn voor jouw specifieke applicatie. Het goede nieuws is dat er een paar manieren zijn om dit te doen.

Bijvoorbeeld, de officiële Git hooks documentatie bevat een aantal van de meest voorkomende parameters. Maar de beste aanpak is om een van de voorbeeld Git hooks te openen. Deze bestaan uit een mini-gids over hoe de hook te scripten en zullen parameter definities voor je bevatten:

Een voorbeeld van een Git hook-bestand in NeoVim op macOS. Het toont een gedeelte met commentaar waarin wordt uitgelegd hoe de hook moet worden gecodeerd, samen met speciale parameters die daarin kunnen worden gebruikt. Er is ook een gedeeltelijke voorbeeld-bash-code voor de hook.
Een voorbeeld Git hook bestand in NeoVim.

Deze zijn een uitstekende manier om Git hooks onder de knie te krijgen en kunnen je zelfs een eind op weg helpen bij het coderen ervan.

Omgevingsvariabelen

Git hooks kunnen argumenten ophalen van commandoregel argumenten, en stdin, zoals we hebben besproken. Ze kunnen echter ook argumenten ophalen uit de omgeving zelf zoals die draait binnen een bash shell.

Deze omgevingsvariabelen laten je het gedrag van je Git hooks aanpassen en beslissingen nemen gebaseerd op verschillende aspecten van de Git workflow. Op deze manier kun je dynamische en context-bewuste Git hooks maken. Je kunt ze bijvoorbeeld gebruiken om commitberichten te valideren, toegang tot specifieke branches te regelen of aangepaste acties te starten op basis van de identiteit van de auteur.

Het opsommen van alle omgevingsvariabelen valt ook buiten het bereik van dit artikel. We raden je aan om de Git documentatie en voorbeeldhooks te bekijken voor hints over welke variabelen het zal gebruiken.

De waarden van omgevingsvariabelen testen

Git stelt meestal automatisch verschillende omgevingsvariabelen in, afhankelijk van de hook die het callt. Als zodanig kan dit problemen voor je veroorzaken als je je niet bewust bent van wat er ingesteld wordt. Neem bijvoorbeeld het volgende resultaat voor de GIT_REFLOG_ACTION variabele voor de pre-rebase en post-merge hooks:

  • pre-rebase. GIT_REFLOG_ACTION=rebase
  • post-merge. GIT_REFLOG_ACTION=’pull other master’

Gelukkig is er een manier om te testen wat Git zal doen met omgevingsvariabelen door een klein fragment binnen je hook te gebruiken:

#!/bin/bash

echo Running $BASH_SOURCE
set | egrep GIT
echo PWD is $PWD

Om de code samen te vatten: regel 2 print het script dat op dat moment draait; regel 3 stelt alle omgevingsvariabelen in om weer te geven, filtert ze dan op die met “GIT” in de naam; regel 4 print de huidige werkmap.

Als je dit uitvoert, zie je uitvoer die overeenkomt met de omgevingsvariabelen die bij je hook horen. Vanaf hier heb je de kennis om ervoor te zorgen dat je eigen Git hooks omgevingsvariabelen kunnen gebruiken op de manier die jij wilt.

Tips en trucs om je Git Hooks te beheren en te delen

Het optimaal beheren van Git hooks binnen een team of organisatie is cruciaal om consistente development te garanderen en je workflows op een efficiënte manier te automatiseren. Neem bijvoorbeeld het toewijzen van een speciale hooks directory. Er zijn twee adviezen die we je hier kunnen geven:

  • Maak een centrale repository of gedeelde locatie waar je gestandaardiseerde hooks opslaat. Je kunt die hooks hergebruiken in meerdere projecten en klonen of linken naar de repository voor globale toegang.
  • Organiseer je hooks in een register of mappenstructuur. Dit maakt het gemakkelijk voor je team om de hooks die ze nodig hebben te vinden en te gebruiken.

Hoe waarschijnlijker het is dat hooks in meerdere projecten voorkomen, hoe groter het belang van documentatie. Je moet uitgebreide documentatie bijhouden die het doel, het gebruik en de configuratieopties voor elke hook in de repo beschrijft. Codebeoordelingen en updatestrategieën voor deze globale hooks zijn ook essentieel.

We raden je ook aan om aangepaste hooks op te slaan in het versiebeheersysteem (VCS), samen met de codebase van je project. Dit zorgt ervoor dat het hele team toegang heeft tot de hele bibliotheek van hooks.

Server-side Git hooks gebruiken

Server-side hooks worden uitgevoerd op de server die de centrale Git repo host. Als zodanig kun je beleidsregels afdwingen, controles uitvoeren of acties starten aan de server kant.

Je hebt twee opslagmogelijkheden voor je server-side hooks: binnen het VCS naast je project of in aparte repositories.

Server-side hooks opslaan met behulp van een VCS

Er zijn twee voordelen aan het gebruik van je VCS om hooks voor de server op te slaan. Ten eerste kun je ervoor zorgen dat de hooks dezelfde versiebeheer en onderhoud hebben als de rest van je codebase. Ten tweede hoef je maar één repository te clonen om toegang te krijgen tot zowel de projectcode als de hooks.

Echter, afhankelijk van de aard van de specifieke hooks, kan het opslaan ervan in dezelfde repo beveiligingsproblemen opleveren als die hooks toegang hebben tot gevoelige informatie. Bovendien, als de hooks complex zijn of specifieke configuraties vereisen, kan het de complexiteit van je hoofdrepository vergroten.

Server-side hooks opslaan in aparte repo’s

Door server-side hooks in aparte repo’s te bewaren, kun je ze onafhankelijk van je codebase updaten en versiebeheer uitvoeren, wat potentiële conflicten kan verminderen. Deze modulariteit kan meer flexibiliteit bieden.

Bovendien kun je die hooks opslaan in repositories met beperkte toegang. Dit helpt je het risico op blootstelling van gevoelige gegevens te verminderen.

Het onderhouden van meerdere repositories kan daarentegen extra inspanning kosten. Als hooks afhankelijk zijn van specifieke versies van je hoofdcode, kan het een uitdaging zijn om wijzigingen tussen je repositories te coördineren.

Hookinstallaties automatiseren

Het automatiseren van hookinstallaties in meerdere repositories kan tijd besparen en zorgen voor consistentie in je ontwikkelworkflow. Door scripts en templates te gebruiken, kun je eenvoudig hooks installeren in verschillende repositories zonder handmatige tussenkomst.

Het proces begint met een speciale repository die je algemene hooks bevat. Je wilt deze standaardiseren: vermijd bijvoorbeeld het hardcoden van paden of waarden die specifiek zijn voor een enkele repo.

Vanaf hier kun je beginnen met het schrijven van je installatiescript. De volgende pseudocode zal bijvoorbeeld de templaterepo van een hook klonen en de hooks kopiëren (of ‘symlinken’) naar de .git/hooks map van elke repository:

# Example installation script
# Usage: ./install_hooks.sh /path/to/repository
TEMPLATE_REPO="https://github.com/yourusername/hooks-template.git"
REPO_PATH="$1"
REPO_NAME=$(basename "$REPO_PATH")

# Clone the template repository
git clone --depth 1 "$TEMPLATE_REPO" "$REPO_NAME-hooks"

# Copy or symlink hooks to the repository
cp -r "$REPO_NAME-hooks/hooks" "$REPO_PATH/.git/"
rm -rf "$REPO_NAME-hooks"
echo "Hooks installed in $REPO_NAME”

Zodra je je wijzigingen hebt opgeslagen, kun je het installatiescript uitvoeren voor elke repo waar je de hooks wilt installeren:

./install_hooks.sh /path/to/repository1
./install_hooks.sh /path/to/repository2
# …

Breng wijzigingen aan in de templaterepository wanneer je hooks wilt bijwerken of toevoegen. De volgende keer dat je het installatiescript in een repository uitvoert, worden de bijgewerkte hooks geïnstalleerd.

Git templates

Met Git templates kun je algemene hooks en configuraties definiëren voor nieuwe repositories. Ze bieden een systematische aanpak om je te helpen setups, configuraties en andere elementen te automatiseren als je nieuwe repositories maakt of kloont. Zo kun je ervoor zorgen dat elke repo voldoet aan de door jou gevolgde practices.

Als je eenmaal een templatemap hebt gemaakt en je hookscripts hebt toegevoegd, kun je Git configureren om de map te gebruiken als template voor nieuwe repositories. Je kunt dit globaal of lokaal per gebruiker instellen.

Voor globale configuraties wijs je naar je hooks-template map:

git config --global init.templateDir /path/to/hooks-template

Voor lokale configuraties kun je de exacte repo opgeven:

git init --template=/path/to/hooks-template

Als je een nieuw repository aanmaakt met git init of een bestaand repository clonet, dan zal Git automatisch de inhoud van je hooks-template map naar de .git map in de nieuwe repo kopiëren.

Tenslotte, waar templatehooks generiek kunnen zijn, kun je ook custom hooks toestaan gebaseerd op specifieke behoeften. Een script zou bijvoorbeeld kunnen controleren op een repository-specifiek hook configuratiebestand en het gebruiken als het aanwezig is.

Best practices om je te helpen om veilig Git hooks te onderhouden

Het gebruik van Git hooks kan waardevol zijn voor procesautomatisering en het afdwingen van best practices. Maar dit kan ook kwetsbaarheden met zich meebrengen als je je hooks niet goed genoeg beheert.

Hier is een korte lijst van werkwijzen die je zou kunnen implementeren voor je eigen hooks:

  • Zorg ervoor dat je permissies voor hooks controleert en beperkt, vooral als het externe samples zijn.
  • Valideer en sanitize altijd je invoerparameters om code-injecties te beperken. Gebruik best practices rond beveiliging, zoals het vermijden van direct gebruik van user input in je scripts.
  • Zorg ervoor dat hooks geen vertrouwelijke informatie bevatten. Dit is waar omgevingsvariabelen of veilige opslag enorme waarde bieden.
  • Controleer en test hooks regelmatig om onbedoeld gebruik van resources te voorkomen. Dit kan zelfs leiden tot DDoS aanvallen (Distributed Denial of Service).

Je wilt ook een grondig en uitgebreid test- en controleproces implementeren. Dit zal kwetsbaarheden en andere fouten in de toekomst helpen voorkomen.

Validatie

We gaan het nu hebben over het implementeren van goede validatie en foutafhandeling voor je hooks. Dit is cruciaal om betrouwbaarheid, stabiliteit en veiligheid te garanderen.

Je wil bijvoorbeeld altijd alle invoer of parameters valideren die je hookscripts ontvangen. Er is echter nog veel meer dat je kunt doen om een goede validatie te garanderen. Je kunt ervoor zorgen dat de repository in de verwachte state is om de hook succesvol te laten draaien. Bijvoorbeeld, in een pre-commit hook, controleer of je de benodigde bestanden test voor de commit.

Een deel van de iTerm-app voor macOS, met een voorbeeld van een Git-hook geopend in een NeoVim-venster. Er is een klein stukje code voor een pre-push hook, met een exit 0-code aan het einde van de suite.
Een deel van een Git hook bestand met de exit 0 code als eindregel.

Foutafhandeling zal ook waardevol zijn. Exit codes zijn net zo cruciaal in hooks als in je codebase, net als foutlogs en informatieve foutmeldingen. Graceful failure zou hier je doel moeten zijn, net als bij grotere codebases.

Natuurlijk kunnen je hooks in een echt scenario complexere validatie en foutafhandeling nodig hebben. Dit betekent dat regelmatig testen nog belangrijker is dan voorheen.

Onopzettelijke destructieve acties

Ongelukjes gebeuren, dus het instellen van je Git hooks om deze ongewenste destructieve acties te voorkomen is cruciaal om dataverlies of schade te voorkomen. Hooks kunnen in wezen fungeren als vangnetten door de gebruiker te vragen om mogelijk schadelijke acties.

Pre-ontvangst en pre-commit hooks werken hier goed. Laten we snel bekijken hoe beide kunnen helpen:

  • Pre-receive hooks helpen voor server-side controles. Deze worden geactiveerd voordat nieuwe branches of tags van de client worden geaccepteerd. Je script moet binnenkomende verwijzingen onderzoeken, controleren op acties zoals geforceerde pushes of branchverwijderingen en de gebruiker om bevestiging vragen. Je zult ook de gepushte referenties willen analyseren om te bepalen of er acties zoals geforceerd pushen (--force) of verwijderen van branches bij betrokken zijn.
  • Pre-commit hooks werken aan de client-side en draaien voordat je een commit afrondt. Hoewel het niet direct destructieve acties op de server zal voorkomen, kan het helpen om lokale fouten te voorkomen voordat je gaat pushen. Je script zou de opgevoerde wijzigingen moeten analyseren en moeten zoeken naar elementen zoals force push commando’s in commitberichten. Toon van daaruit een waarschuwing of foutmelding voor de gebruiker.

Echter, welke praktijken je ook implementeert, ze moeten veilig, efficiënt en optimaal zijn voor jouw behoeften. Dit vereist een grondige review en teststrategie.

Git Hooks beoordelen en testen

Het nakijken en testen van hooks is essentieel om er zeker van te zijn dat ze goed werken en aansluiten op je ontwikkel workflow. Beoordelingen door collega’s, duidelijke documentatie, een overvloed aan commentaar en meer kunnen ervoor zorgen dat hooks klaar zijn voor productie.

Als het op testen aankomt, is het belangrijk om dit geïsoleerd te doen met diverse voorbeeldgegevens. Je zou ook geautomatiseerde regressie- of integratietests kunnen implementeren.

Tot slot raden we je aan om hooks te testen in verschillende omgevingen (zoals je ontwikkel-, test- en productieservers) om ervoor te zorgen dat ze consistent gedrag vertonen. Een real-time logging setup zal hierbij helpen, omdat het kan laten zien wat er gebeurt als gegevens van server naar server gaan.

Problemen met hooks oplossen

Zoals met elke codebase, kan het zijn dat je ook je hooks moet troubleshooten – zelfs na een paar pogingen. In feite, wat voor type Git hook je ook hebt, je zult merken dat dezelfde fouten steeds weer opduiken. Veel van deze zullen eenvoudige problemen zijn die invloed hebben op alle soorten projecten, zoals syntaxisfouten, toestemmingsproblemen, het gebruik van relatieve of hardcoded paden, en nog veel meer.

Het is echter ook een goed idee om te controleren op ontbrekende dependencies, omdat sommige hooks afhankelijk zijn van externe tools, bestanden of bibliotheken. Als zodanig moet je ze beschikbaar maken in de omgeving waar je de hook uitvoert.

Er zijn echter specifieke problemen die kunnen opduiken met Git hooks. Bijvoorbeeld, hooks moeten afsluiten met een non-zero statuscode om een mislukking aan te geven. Bovendien zouden hooks geen oneindige loops moeten bevatten. Hiermee kun je namelijk onverwacht gedrag veroorzaken en je workflow verstoren.

Je kunt ook merken dat conflicten tussen twee hooks onbedoelde interacties en gevolgen hebben. Ook zogenaamde ‘race conditions’ kunnen je verwachtingen verstoren. Dit is wanneer twee of meer hooks door vergelijkbare gebeurtenissen worden geactiveerd, maar de ene eerder wordt voltooid dan de andere – dit heeft invloed op het eindresultaat dat je verwacht.

Hier zijn reviews en tests van vitaal belang. Het bijhouden van documentatie is ook belangrijk om problemen te voorkomen en ervoor te zorgen dat hooks werken zoals je verwacht.

Over documentatie gesproken, Git’s eigen referentiemateriaal is essentieel leesvoer. In feite, samen met dit artikel en misschien de onafhankelijke Git Hooks gidssite (met behulp van GitHub Pages), zou je niet al te veel leesmateriaal nodig moeten hebben.

De externe Git Hooks-website , met een inleiding tot hooks en een uitleg. Er wordt gebruik gemaakt van zwarte tekst op een witte achtergrond. In de hoek staat het GitHub-symbool, wat aangeeft dat de site wordt gehost op GitHub Pages.
De GitHooks gids website.

Je zou echter ook naar apps kunnen kijken om je te helpen Git hooks te beheren. Lefthook heeft regelmatige updates en veel ondersteuning op GitHub, terwijl Husky geweldig is voor het linten van je commitberichten.

De voordelen van het integreren van hooks in continue integratie (CI/CD) pipelines

CI/CD pijplijnen werken goed met Git hooks, omdat die scripts je kunnen helpen taken te automatiseren, consistente kwaliteit te garanderen en veiligheidscontroles te bieden.

Met pre-commit hooks kun je bijvoorbeeld code kwaliteitscontroles uitvoeren, zoals linting, statische analyse en opmaak. Als het op testen aankomt, kun je eenheidstests, testsuites of andere geautomatiseerde controles starten in de pre-commit fase. Aan de andere kant kun je met pre-push hooks integratietests, beveiligingsscans en meer uitvoeren.

Er zijn veel voordelen die je kunt halen uit het gebruik van hooks binnen je CI/CD pipelines:

  • Consistentie. Met hooks kun je consistente werkwijzen afdwingen voor alle commits en deployments, wat fouten over de hele linie zal verminderen.
  • Geautomatiseerde controles. Je kunt kwaliteitscontroles van code, testen, beveiligingsscans en andere belangrijke taken automatiseren. Dit vermindert handmatige inspanning en zorgt ervoor dat je meer tijd overhoudt voor andere taken.
  • Vroegtijdige probleemdetectie. Met hooks kun je problemen in een vroeg stadium van het ontwikkelproces opsporen, waardoor ze zich niet verder kunnen verspreiden in je pipeline.
  • Minder risico’s bij deployments. Met geautomatiseerde controles en tests die worden geactiveerd door hooks, kan het risico van het deployen van foutieve code aanzienlijk worden verminderd.

Omdat je met Kinsta’s API CI/CD pipelines kunt opzetten, kun je ook hier Git hooks integreren. Met Kinsta kun je je hele repo pullen vanaf een externe locatie en je kunt pushen met een externe plugin zoals WP Pusher.

De WP Pusher homepage met een blauwe achtergrond, met een slogan en beschrijving voor de plug-in, en een screenshot van het instellingenscherm binnen het WordPress-dashboard.
De homepage van WP Pusher.

Natuurlijk betekent dit ook dat je de optie hebt om Git hooks te gebruiken. Als zodanig kan je Kinsta installatie gebruik maken van deze krachtige scripts binnen je repo.

Samenvatting

Git is een essentiële tool voor elk ontwikkelproject, maar één aspect ervan in het bijzonder kan je coderings- en deploymentworkflow een enorme impuls geven. Met Git hooks kun je scripts maken in een aantal talen om verschillende aspecten van je versiebeheerproces te automatiseren. Het is een eenvoudig concept met een ietwat complexe uitvoering.

Ons artikel laat je zien hoe je geavanceerde technieken kunt gebruiken om Git hooks optimaal te benutten. Je kunt ze zowel lokaal als server-side gebruiken, ze dynamisch maken door parameters en variabelen te gebruiken, met meerdere remote repo’s werken en meer. We gaan zelfs zover dat we stellen dat Git hooks op dit punt wel eens je geheime wapen zouden kunnen worden om de productiviteit, de kwaliteit van de code en de doorlooptijd van je project te verhogen.

Heb je vragen over Git hooks en hoe ze te gebruiken? Laat het ons weten in de commentsectie hieronder!

Jeremy Holcombe Kinsta

Content & Marketing Editor at Kinsta, WordPress Web Developer, and Content Writer. Outside of all things WordPress, I enjoy the beach, golf, and movies. I also have tall people problems ;).