Git non deve essere necessariamente complesso, ma ci sono alcuni suoi aspetti che sono intricati e che richiedono una comprensione più approfondita: gli hook di Git, ad esempio. Si tratta di script che Git esegue automaticamente in base a determinati eventi.

Per quanto possano essere usati in maniera semplificata, è possibile utilizzarli anche in modo molto più efficace. Tuttavia, per farlo, è necessario comprendere tutti gli ingranaggi che compongono l’intero sistema.

In questo post analizzeremo le tecniche avanzate per i Git Hook che includono alcune nozioni di base, come crearli e installarli e altro ancora.

Inoltre, spiegheremo come funzionano i parametri degli hook e le variabili d’ambiente, offriremo alcuni suggerimenti e trucchi, esamineremo i metodi di risoluzione dei problemi e molti altri argomenti.

Nozioni di base di Git Hooks: un’infarinatura

Una delle caratteristiche principali di Git sono gli hook: un potente meccanismo che permette di automatizzare le attività, applicare gli standard e garantire flussi di lavoro coerenti durante il ciclo di vita di un progetto.

Gli hook di Git sono script che vengono eseguiti automaticamente in punti specifici del flusso di lavoro di Git. Potete usarli per personalizzare ed estendere il comportamento di Git in base alle esigenze del progetto. Gli hook garantiscono il mantenimento della qualità del codice, l’esecuzione dei test e l’organizzazione delle distribuzioni senza problemi.

Git offre diversi tipi di hook, ognuno dei quali si attiva in fasi diverse del workflow di Git:

  • Pre-commit. Questi hook vengono eseguiti prima di finalizzare un commit e permettono di applicare stili di codice, eseguire test o verificare la presenza di errori di sintassi.
  • Post-commit. Vengono eseguiti dopo aver creato un commit. È utile per le notifiche o il logging.
  • Pre-push. Questo hook si attiva prima del push del codice e permette di eseguire test di integrazione, verificare la compatibilità o garantire la qualità.
  • Post-push. L’ultimo hook viene eseguito dopo aver completato un push. Per questo motivo è utile per distribuire il codice in produzione o per aggiornare la documentazione.

Troverete gli hook nella directory .git/hooks del repository Git. Ci sono anche degli esempi di hook: potete usarli come template per creare i vostri script personalizzati. Gli hook coprono una serie di azioni e utilizzano il prefisso sample- come riferimento:

Una schermata del Finder di macOS che mostra una directory locale contenente 13 file hook di esempio bianchi su sfondo grigio.
Una directory Git locale che mostra i file di esempio degli hooks.

Gli hook si attivano durante varie azioni di Git. Ad esempio, un hook pre-commit viene eseguito quando eseguite il commit delle modifiche e un hook pre-push si attiva prima di eseguire il push in remoto. Una volta che avrete compreso meglio questi trigger, potrete distribuire gli hook in modo più strategico per rafforzare il controllo di qualità e ottimizzare il vostro flusso di lavoro.

Come creare e installare gli hook Git personalizzati

Creare e installare gli hook Git personalizzati di base può essere un processo complesso. Tuttavia, i fondamenti che utilizzeremo qui serviranno per sviluppare in seguito degli hook avanzati. Vediamo alcuni concetti che si applicano a tutti gli hook che creiamo e installiamo.

Scegliere un tipo di hook appropriato

L’impiego del tipo di hook giusto per il proprio caso d’uso specifico è un primo passo importante da compiere. Innanzitutto, è necessario capire il vostro workflow e le vostre esigenze di sviluppo. Ecco una rapida lista di considerazioni a riguardo:

  • Innanzitutto, considerate le varie fasi del vostro processo, come la codifica, i test e la distribuzione. Inoltre, individuate i punti in cui il processo potrebbe trarre vantaggio dall’automazione e dai controlli.
  • Da lì, individuate i punti del vostro flusso di lavoro in cui si verificano spesso errori o incongruenze. I Git Hook personalizzati possono essere d’aiuto in questo caso. Ad esempio, se dimenticate di eseguire i test prima di un commit, un hook pre-commit può risolvere il problema.
  • Poi, considerate quando volete eseguire l’hook all’interno del flusso di lavoro. Ad esempio, se volete assicurarvi che tutti i commit rispettino gli standard di codifica, un hook pre-commit è la soluzione giusta. Se invece volete convalidare il codice prima di inviarlo in remoto, un hook pre-push sarà più adatto.
  • Infine, assicuratevi che il tipo di hook scelto sia compatibile con il vostro ambiente di sviluppo e con gli strumenti che utilizzate. Considerate il linguaggio di scripting che utilizzerete per l’hook e il suo ambiente di esecuzione.

A questo punto, dovreste essere in grado di definire obiettivi chiari per l’hook. Può anche darsi che ogni obiettivo richieda un tipo di hook diverso. Tuttavia, anche se la tentazione di creare script per ogni possibile scenario è forte, è bene concentrarsi prima sui punti critici.

Dare un nome e posizionare gli hook Git personalizzati

Denominare e posizionare correttamente gli hook Git personalizzati è fondamentale per garantirne la funzionalità e la manutenibilità. Come le funzioni, i file, i nomi delle classi e altro ancora del codice, anche gli hook Git dovrebbero avere una convenzione di denominazione coerente e descrittiva.

Se gli hook dovranno supportare più progetti nel tempo come template, potreste voler utilizzare dei prefissi, magari con le iniziali degli sviluppatori, un dipartimento o il nome di un’azienda. In generale, i Git Hook utilizzano lettere minuscole e trattini per una maggiore leggibilità: ad esempio, mio-progetto-pre-commit.

Inoltre, mentre potete memorizzare gli hook Git nella cartella .git/hooks del vostro repo, gli hook personalizzati dovrebbero essere inseriti in una cartella separata all’interno della cartella principale del progetto. In questo modo si eviteranno sovrascritture accidentali durante un aggiornamento di Git. Tuttavia, dovreste implementare il controllo di versione per questi hook insieme al resto del codice del vostro progetto.

Come creare un hook Git personalizzato di livello base

Il modo tipico per scrivere un hook Git di base è quello di creare un nuovo file con il nome dell’hook scelto (ad esempio pre-commit) nella directory degli hook. Elencheremo i nomi degli hook più avanti quando parleremo dei parametri.

Prima di aprire un file per lavorarci, dovete assicurarvi che sia eseguibile utilizzando il seguente frammento di riga di comando:

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

Ricordatevi di sostituire i placeholder con le informazioni corrette. Faremo riferimento a questo snippet in tutto il post, poiché dovrebbe essere un’azione tipica ogni volta che si crea un nuovo hook Git.

Una volta che il file è eseguibile e aperto, aggiungete la vostra logica personalizzata utilizzando il linguaggio di scripting che preferite. Può trattarsi di Bash, Python, Ruby e altri. La creazione di questi linguaggi va ovviamente al di là dell’argomento che tratteremo in questa sede. Tuttavia, in seguito sono previsti alcuni esempi di pseudocodice per illustrare casi d’uso e scenari specifici.

Infine, prima di effettuare il commit di qualsiasi modifica, testate il vostro hook tentando di eseguire l’azione correlata (come ad esempio il commit). Questo è l’approccio di base alla creazione di Git Hook, ma ci sono molti casi d’uso avanzati. Li analizzeremo nel prossimo paragrafo.

Come creare e installare hook personalizzati avanzati

La creazione di Git Hook di livello base sarà un’attività che eseguirete spesso nel corso della vostra carriera di sviluppatori. Tuttavia, in molte situazioni sono necessari hook più avanzati e complessi. Di seguito vedremo alcuni casi d’uso e alcuni esempi di hook per una serie di scenari comuni.

Creare un hook che imponga lo stile del codice usando i linter

L’utilizzo di un linter per imporre lo stile del codice è un’applicazione fantastica per gli hook di Git. Può aiutare a mantenere la qualità del codice coerente in tutto il repository e dovrebbe essere un’applicazione molto utile.

Naturalmente, dovrete scegliere un linter che si adatti al linguaggio di programmazione del vostro progetto. Ad esempio, Black è fantastico per Python. Qui useremo ESLint per JavaScript per creare un hook di pre-commit.

Per prima cosa, installate il linter come pacchetto globale o locale all’interno del vostro progetto. A tal fine avrete bisogno di Node.js e npm:

npm install eslint --save-dev

Successivamente, andate alla directory degli hooks all’interno del vostro repo. Create il vostro file di pre-commit, quindi scrivete uno script che esegua il linter sui vostri file in fase di stage. L’hook deve impedire il commit se il linter trova dei problemi. Ecco un esempio approssimativo:

#!/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

Una volta che vi sarete assicurati che l’hook sia eseguibile, testatelo con un commit. L’hook pre-commit dovrebbe eseguire il linter. Se ci sono violazioni dello stile del codice, non potrete completare il commit finché non avrete risolto i problemi.

Naturalmente, dovreste scrivere un hook che funzioni con il vostro linguaggio di programmazione e il vostro linter, in base al vostro progetto. Ad esempio, potreste estendere questo esempio con le impostazioni di configurazione di linter, integrandolo con il vostro processo di build e altro ancora.

Implementare un hook per eseguire i test prima di un commit

L’implementazione di un hook pre-commit per eseguire i test prima di un commit è un modo eccellente per individuare tempestivamente eventuali problemi. In questo modo, potrete assicurarvi di eseguire il commit solo di codice affidabile.

Per questo esempio, utilizzeremo il framework di testing Jest per JavaScript. Dovrete installare qualcosa di adatto al vostro progetto (come sempre):

npm install jest --save-dev

Come per ogni hook, andate nella cartella degli hook, create un nuovo file, dategli un nome e rendetelo eseguibile. Da qui, scrivete uno script che esegua i test su tutti i file in fase di commit. Ecco un modello approssimativo:

#!/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

Quando si tenta di eseguire il commit delle modifiche, l’hook eseguirà i test sui file in fase di stage. Il commit si interromperà per qualsiasi test fallito e dovrete risolvere i problemi prima di eseguire nuovamente il commit.

Sviluppare un hook per automatizzare il versioning e il tagging

Un modo eccellente per semplificare il processo di rilascio è automatizzare il versioning e il tagging all’interno di Git. In questo modo si garantirà un versioning coerente in tutta la base di codice.

Per iniziare, scegliete uno schema di versioning adatto al vostro progetto. Questo esula dallo scopo dell’articolo, ma gli schemi più comuni includono il Semantic Versioning (SemVer) o un modello di versioning personalizzato.

Poi, decidete esattamente cosa farà il vostro hook. Ad esempio, potrebbe leggere la versione corrente, incrementarla secondo lo schema scelto e aggiornare i file necessari con la nuova versione. Dovrete anche scrivere uno script per la creazione di tag in base alla versione che utilizzi i comandi Git per creare tag leggeri o annotati.

Una volta creati e impostati i permessi per il vostro file, potete iniziare a scrivere il vostro hook. Può trattarsi di un hook complesso e molto specifico che può anche cambiare da progetto a progetto. Tuttavia, la maggior parte degli hook di questo tipo include i seguenti elementi:

  • Una funzione che incrementa una parte specifica di una stringa di versione (ad esempio, 1.2.3) e restituisce la nuova versione.
  • La possibilità di leggere la versione corrente da un file di versione dedicato.
  • Una funzione per calcolare il nuovo numero di versione, compresa la parte specifica da incrementare. Ad esempio, 0 per major, 1 per minor, 2 per patch.

Da qui, lo script deve aggiornare il file di versione con il nuovo numero, creare un tag leggero con la nuova versione e, facoltativamente, inviare il nuovo tag a un repository remoto. Una volta effettuate le modifiche, l’hook farà in modo che ogni commit sia associato a una versione e a un tag appropriati.

Probabilmente vorrete adattare ulteriormente questo hook alle esigenze del vostro progetto. Ad esempio, potreste gestire casi come la creazione di tag iniziali, la gestione dei conflitti di versione e l’aggiornamento dei riferimenti di versione nei file.

Capire i parametri dell’hook e le variabili d’ambiente

Uno dei motivi per cui gli hook di Git sono così potenti è il modo in cui gestiscono le variabili dinamiche. Tuttavia, questo può essere un concetto complesso da comprendere. Di seguito analizzeremo sia le variabili d’ambiente che i parametri degli hook, iniziando da questi ultimi.

Come i parametri passano agli hook

Gli hook possono ricevere parametri specifici da Git per accedere a informazioni contestuali dalla vostra base di codice principale. Git imposta i parametri in modo automatico al momento dell’esecuzione e, sebbene nella maggior parte dei casi non sia necessario definirli, potrebbe essere necessario dichiararli. È essenziale comprenderli per sviluppare degli hook efficaci.

Ecco una panoramica dei punti chiave dei parametri degli hook:

  • Gli hook di Git utilizzano variabili posizionali, dove $1 si riferisce al primo parametro, $2 al secondo parametro e così via. Questi parametri non sono arbitrari: hanno significati e scopi specifici. Per questo motivo, anche se non sono “ufficiali”, rappresentano delle convenzioni accettate per accedere ai valori dei parametri.
  • L’ordine dei parametri segue uno schema specifico. Git passa questi parametri al vostro script hook in un ordine predeterminato basato sul contesto dell’evento hook.
  • I nomi delle variabili riflettono lo scopo generale dei parametri. Ad esempio, $1 spesso contiene il percorso di un file mentre $2 potrebbe essere la fonte di un’azione.

Se doveste aggiungere un parametro che l’hook non può chiamare, lo script non sarà generalmente in grado di utilizzarlo. I parametri sono specifici per un particolare hook e contesto di esecuzione. Per evitare problemi, dovreste utilizzare solo parametri documentati. Tuttavia, potete assegnare il valore di un parametro posizionale a un’altra variabile e poi utilizzarlo nel vostro script:

#!/bin/sh

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

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

In questo caso, la variabile EXAMPLE avrà lo stesso valore di $1, che è il percorso del file del messaggio di commit. Tuttavia, l’utilizzo dei nomi delle variabili documentati rende il codice più comprensibile.

Tenete presente che in alcuni casi utilizzerete lo standard input (stdin) per definire i parametri, nel qual caso dovrete inserire questi elementi nei vostri hook.

Trovare i valori e le definizioni dei parametri degli hook Git

Poiché ogni hook di Git avrà i suoi parametri, è probabile che abbiate bisogno di un riferimento per sapere quali sono per la vostra specifica applicazione. La buona notizia è che ci sono alcuni modi per farlo.

Ad esempio, la documentazione ufficiale degli hook Git include alcuni dei parametri più comuni. Tuttavia, l’approccio migliore è quello di aprire uno dei Git hook di esempio. Questi consistono in una mini-guida su come eseguire lo script dell’hook e includono le definizioni dei parametri:

Un esempio di file Git hook in NeoVim su macOS. Mostra una sezione commentata che spiega come codificare l'hook, insieme ai parametri dedicati utilizzabili all'interno. C'è anche un esempio parziale di codice bash per l'hook.
Un file di esempio di hook Git in NeoVim.

Questi esempi sono un ottimo modo per familiarizzare con gli hook Git e possono anche farvi fare un po’ di strada quando si tratta di codificarli.

Variabili d’ambiente

I Git Hook possono recuperare argomenti da quelli della riga di comando e da stdin,, come abbiamo detto. Tuttavia, possono anche recuperare argomenti dall’ambiente stesso mentre viene eseguito all’interno della shell bash.

Queste variabili d’ambiente permettono di personalizzare il comportamento dei vostri Git Hook e di prendere decisioni basate su vari aspetti del flusso di lavoro Git. In questo modo, potete creare dei Git Hook dinamici e consapevoli del contesto. Ad esempio, potete usarli per convalidare i messaggi di commit, controllare l’accesso a branch specifici o attivare azioni personalizzate in base all’identità dell’autore.

Elencare tutte le variabili d’ambiente va oltre lo scopo di questo post. Vi consigliamo di consultare la documentazione di Git e gli hook di esempio per avere indicazioni sulle variabili da utilizzare.

Testare i valori delle variabili d’ambiente

In genere Git imposta automaticamente diverse variabili d’ambiente a seconda dell’hook che chiama. Questo può causare dei problemi se non siete a conoscenza delle variabili impostate. Ad esempio, prendiamo il seguente risultato per la variabile GIT_REFLOG_ACTION per gli hook pre-rebase e post-merge:

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

Fortunatamente, c’è un modo per verificare cosa fa Git con le variabili d’ambiente utilizzando un piccolo snippet all’interno del vostro hook:

#!/bin/bash

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

Per riassumere il codice, la riga due stampa lo script in esecuzione; la riga tre imposta tutte le variabili d’ambiente da visualizzare, quindi filtra quelle con “GIT” nel nome; la riga quattro stampa la directory di lavoro corrente.

Una volta eseguito, vedrete l’output corrispondente alle variabili d’ambiente associate al vostro hook. Da qui avrete le conoscenze necessarie per assicurarvi che i vostri Git Hook possano utilizzare le variabili d’ambiente nel modo che preferite.

Consigli e trucchi per gestire e condividere i vostri Git Hook

La gestione degli hook Git all’interno di un team o di un’azienda è fondamentale per garantire pratiche di sviluppo coerenti e automatizzare i flussi di lavoro in modo efficiente. Per esempio, prendiamo il semplice atto di assegnare una directory dedicata agli hook. Possiamo darvi due consigli:

  • Create un repository centrale o una posizione condivisa in cui memorizzare gli hook standardizzati. Potete riutilizzare questi hook in più progetti e clonare o collegare il repository per avere un accesso globale.
  • Organizzate i vostri hook in un registro o in una struttura di directory. In questo modo il vostro team potrà trovare e utilizzare facilmente gli hook di cui ha bisogno.

Più è probabile che gli hook vengano utilizzati in più progetti, maggiore è l’importanza della documentazione. dovreste mantenere una documentazione completa che illustri lo scopo, l’uso e le opzioni di configurazione di ogni hook all’interno del repo. Anche le revisioni del codice e le strategie di aggiornamento per questi hook globali saranno essenziali.

Vi consigliamo anche di archiviare gli hook personalizzati nel sistema di controllo delle versioni (VCS) insieme alla base di codice del vostro progetto. In questo modo si garantisce che tutto il team abbia accesso all’intera libreria di hook.

Usare gli hook Git lato server

Gli hook lato server vengono eseguiti sul server che ospita il repo Git centrale. In questo modo, potete applicare le politiche, eseguire controlli o attivare azioni sul lato server.

Avete due opzioni di archiviazione per i vostri hook lato server: all’interno del VCS insieme al vostro progetto o in repository separati.

Memorizzare gli hook lato server usando un VCS

L’utilizzo del VCS per memorizzare gli hook lato server presenta due vantaggi. Innanzitutto, potete assicurarvi che gli hook abbiano lo stesso versioning e la stessa manutenzione del resto della base di codice. In secondo luogo, dovrete clonare un solo repository per accedere sia al codice del progetto che agli hook.

Tuttavia, a seconda della natura degli hook specifici, archiviarli nello stesso repository potrebbe sollevare problemi di sicurezza nel caso in cui tali hook accedano a informazioni sensibili. Inoltre, se gli hook sono complessi o richiedono configurazioni specifiche, potrebbe aumentare la complessità del vostro repo principale.

Conservare gli hook lato server in repository separati

Mantenere gli hook lato server in repository separati permette di aggiornarli e di modificarli indipendentemente dalla base di codice, riducendo così i potenziali conflitti. Questa modularità può offrire una maggiore flessibilità.

Inoltre, potete conservare gli hook in repository ad accesso limitato. Questo aiuterà a ridurre il rischio di esposizione di dati sensibili.

Al contrario, la gestione di più repository potrebbe richiedere uno sforzo aggiuntivo. Inoltre, se gli hook si basano su versioni specifiche della vostra base di codice principale, può essere difficile coordinare le modifiche tra i repository.

Automatizzare l’installazione degli hook

Automatizzare l’installazione degli hook su più repository può far risparmiare tempo e garantire la coerenza del flusso di sviluppo. Utilizzando script e template, potete impostare facilmente gli hook nei vari repository senza dover intervenire manualmente.

Il processo inizia con un repository dedicato che contiene gli hook globali. Dovrete standardizzarli: per esempio, evitate di codificare percorsi o valori specifici per un singolo repository.

Da qui potete iniziare a scrivere il vostro script di installazione. Ad esempio, il seguente pseudocodice clonerà il repo modello di un hook e copierà (o “linkerà”) gli hook nella directory .git/hooks di ogni 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”

Una volta salvate le modifiche, potete eseguire lo script di installazione per ogni repo in cui volete installare gli hook:

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

Apportate le modifiche nel repository del modello ogni volta che avete bisogno di aggiornare o aggiungere gli hook. La volta successiva che eseguirete lo script di installazione in un repository, gli hook aggiornati verranno installati.

Template Git

I template Git permettono di definire hook e configurazioni comuni per i nuovi repository. Forniscono un approccio sistematico per aiutarvi ad automatizzare le impostazioni, le configurazioni e altri elementi quando create o clonate nuovi repository. In questo modo potete assicurarvi che ogni repository aderisca alle vostre pratiche tipiche e consolidate.

Una volta creata una directory template e aggiunti gli script hook, potete configurare Git in modo che utilizzi la directory come modello per i nuovi repository. Potete impostarlo su base globale o locale per ogni utente.

Per le configurazioni globali, puntate alla cartella template hooks:

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

Per le configurazioni locali, potete specificare il repo esatto:

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

Ogni volta che create un nuovo repository usando git init o clonate un repository esistente, Git copierà automaticamente il contenuto della directory degli hook template nella directory .git del nuovo repo.

Infine, mentre gli hook template possono essere generici, è anche possibile consentire la personalizzazione degli hooks in base a esigenze specifiche. Ad esempio, uno script potrebbe verificare la presenza di un file di configurazione degli hook specifico per il repository e utilizzarlo se presente.

Pratiche comuni per mantenere sicuri gli hook Git

L’uso degli hook Git può essere molto utile per l’automazione dei processi e l’applicazione delle pratiche più comuni. Tuttavia, questo può comportare la possibilità di introdurre vulnerabilità se non si gestiscono bene gli hook.

Ecco un rapido elenco di pratiche che potreste implementare per i vostri hook:

  • Assicuratevi di controllare e limitare i permessi per gli hook, soprattutto se si tratta di esempi di terze parti.
  • Convalidate e sanificate sempre i parametri di input per evitare le iniezioni di codice. Utilizzate pratiche sicure, come ad esempio evitare l’uso diretto di input dell’utente nei vostri script.
  • Assicuratevi che gli hook non includano informazioni riservate. In questo caso le variabili d’ambiente o l’archiviazione sicura offrono un valore immenso.
  • Esaminate e testate regolarmente gli hook per evitare un consumo involontario di risorse. Questo potrebbe portare ad attacchi DDoS (Distributed Denial of Service).

Dovrete anche implementare un processo di test e revisione completo e approfondito. Questo vi aiuterà a ridurre le vulnerabilità e altri errori in futuro.

Convalida

A questo punto, dovremmo parlare dell’implementazione di una corretta convalida e gestione degli errori per i vostri hook. Questo è fondamentale per garantire affidabilità, stabilità e sicurezza.

Ad esempio, dovete sempre convalidare tutti gli input o i parametri che i vostri script hook ricevono. Tuttavia, potete fare molto di più per garantire una buona validazione. Potete assicurarvi che il repository sia nello stato previsto per l’esecuzione dell’hook. Ad esempio, in un hook pre-commit, controllate che i file necessari siano in fase di staging prima del commit.

Una parte dell'applicazione iTerm per macOS, che mostra un esempio di hook Git aperto in una finestra NeoVim. È presente una piccola sezione di codice per un hook pre-push, con un codice di uscita 0 alla fine della suite.
Una parte di un file di hook Git che mostra il codice di uscita 0 come riga finale.

Anche la gestione degli errori sarà preziosa. I codici di uscita sono fondamentali sia negli hook che nella base di codice, così come i log degli errori e i messaggi di errore informativi. L’obiettivo dovrebbe essere il “Graceful failure”, come nel caso di codebase più grandi.

Naturalmente, in uno scenario reale, i vostri hook potrebbero richiedere una convalida più complessa e una logica di gestione degli errori. Ciò significa che i test regolari sono ancora più importanti.

Azioni distruttive accidentali

Gli incidenti possono capitare, quindi impostare i vostri Git Hook in modo da prevenire queste azioni distruttive indesiderate è fondamentale per salvaguardare i dati da perdite o danni. Gli hook possono essenzialmente fungere da reti di sicurezza attraverso la segnalazione da parte dell’utente di azioni potenzialmente dannose.

Gli hook di pre-ricezione e di pre-commit funzionano bene in questo caso. Vediamo rapidamente come entrambi possono essere utili:

  • Gli hook di pre-ricezione sono utili per i controlli sul lato server. Si attivano prima di accettare nuovi branch o tag dal client. Il vostro script dovrebbe esaminare i riferimenti in arrivo, verificare la presenza di azioni come il force push o la cancellazione di branch e chiedere all’utente una conferma. Dovrete anche analizzare i riferimenti spinti per determinare se comportano azioni come il force pushing (--force) o la cancellazione di branch.
  • Gli hook di pre-commit funzionano sul lato client e vengono eseguiti prima di finalizzare un commit. Anche se non impediscono direttamente azioni distruttive sul server, possono aiutare a prevenire errori locali prima del push. Il vostro script deve analizzare le modifiche in fase di elaborazione e cercare elementi come i comandi di force push nei messaggi di commit. A questo punto, mostrate un messaggio di avvertimento o di errore per l’utente.

Tuttavia, a prescindere dalle pratiche che implementerete, queste devono essere sicure, efficienti e ottimali per le vostre esigenze. Per questo è necessaria una strategia di revisione e test approfondita.

Revisione e test degli hook Git

La revisione e il test degli hook sono essenziali per garantire che funzionino correttamente e che siano in linea con il vostro flusso di sviluppo. Le peer review, una documentazione chiara, l’abbondanza di commenti e altro ancora possono aiutare a garantire che gli hook siano pronti per la produzione.

Quando si tratta di testare, è importante farlo in modo isolato utilizzando dati campione diversi. Potreste anche implementare test di regressione o di integrazione automatizzati.

Infine, vi consigliamo di testare gli hook in ambienti diversi (come i server di sviluppo, di staging e di produzione) per assicurarvi che abbiano un comportamento coerente. Una configurazione di log in tempo reale vi aiuterà in questo senso, in quanto può mostrare cosa succede quando i dati si spostano da un server all’altro.

Come risolvere i problemi degli hook

Come in ogni base di codice, anche in questo caso potreste dover risolvere problemi legati agli hook, anche con diversi tentativi. Infatti, a prescindere dal tipo di hook Git, troverete sempre gli stessi errori. Molti di questi sono semplici problemi che riguardano tutti i tipi di progetti, come errori di sintassi, problemi di permessi, utilizzo di percorsi relativi o hardcoded e molto altro ancora.

Tuttavia, è una buona idea controllare che non ci siano dipendenze mancanti, poiché alcuni hook si basano su strumenti, file o librerie esterne. Per questo motivo, dovete renderli disponibili nell’ambiente in cui eseguite l’hook.

Ci sono però dei problemi specifici che possono verificarsi con gli hook di Git. Ad esempio, gli hook dovrebbero uscire con un codice di stato diverso da zero per indicare un fallimento. Inoltre, gli hook non dovrebbero contenere loop infiniti. Senza questi due elementi, potreste causare un comportamento inaspettato e interrompere il workflow.

Potreste anche scoprire che i conflitti tra due hook provocano interazioni e conseguenze indesiderate. Anche le cosiddette “race condition” possono ostacolare le vostre aspettative. Questo accade quando due o più hook si attivano attraverso eventi simili, ma uno si completa prima dell’altro: questo avrà un impatto sul risultato finale che vi aspettate.

È qui che le revisioni e i test diventano fondamentali. Anche il mantenimento della documentazione è importante per evitare problemi e garantire che gli hook funzionino come ci si aspetta.

A proposito di documentazione, il materiale di riferimento di Git è una lettura essenziale. In effetti, insieme a questo articolo e forse al sito indipendente della guida agli hook di Git (utilizzando GitHub Pages), non dovreste aver bisogno di molto altro materiale da leggere.

Il sito web di Git Hooks di terze parti, che mostra un'introduzione agli hook e una spiegazione. Utilizza testo nero su sfondo bianco. Nell'angolo è presente il simbolo di GitHub, che indica che il sito è ospitato su GitHub Pages.
Il sito web della guida GitHooks.

Tuttavia, potreste voler dare un’occhiata anche alle applicazioni che aiutano a gestire i Git hook. Lefthook ha aggiornamenti regolari e un sacco di supporto su GitHub, mentre Husky è ottimo per il linting dei messaggi di commit.

I vantaggi dell’integrazione degli hooks nelle pipeline di integrazione continua (CI/CD)

Le pipeline CI/CD funzionano bene con gli hook di Git, in quanto questi script possono aiutarvi ad automatizzare le attività, garantire una qualità costante e fornire controlli di sicurezza.

Ad esempio, gli hook pre-commit vi permettono di eseguire controlli di qualità del codice, come il linting, l’analisi statica e la formattazione. Per quanto riguarda i test, potete attivare test unitari, suite di test o altri controlli automatizzati nella fase di pre-commit. Inoltre, gli hook pre-push vi permettono di eseguire test di integrazione, scansioni di sicurezza e altro ancora.

Sono molti i vantaggi che potete trarre dall’uso degli hook nelle vostre pipeline CI/CD:

  • Coerenza. Gli hook permettono di applicare pratiche coerenti in tutti i commit e le distribuzioni, riducendo così gli errori.
  • Controlli automatizzati. Potete automatizzare i controlli di qualità del codice, i test, le scansioni di sicurezza e altre attività importanti. In questo modo ridurrete lo sforzo manuale e avrete più tempo da dedicare ad altre attività.
  • Rilevamento precoce dei problemi. Gli hook vi permetteranno di individuare i problemi nelle prime fasi del processo di sviluppo, evitando che si propaghino nella pipeline.
  • Riduzione dei rischi di distribuzione. Grazie ai controlli e ai test automatici attivati dagli hook, il rischio di distribuire codice difettoso può essere ridotto in modo significativo.

Poiché l’API di Kinsta permette di impostare pipeline CI/CD, potete integrare anche gli hook Git. Kinsta vi permette di scaricare l’intero repo da una postazione remota e consente di effettuare push utilizzando un plugin di terze parti come WP Pusher.

La home page di WP Pusher con uno sfondo blu, che mostra la tagline e la descrizione del plugin e una schermata delle impostazioni nella bacheca di WordPress.
La pagina iniziale di WP Pusher.

Naturalmente, ciò significa che avete anche la possibilità di utilizzare i Git hook. In questo modo, la vostra installazione di Kinsta può sfruttare questi potenti script all’interno del vostro repo.

Riepilogo

Git è uno strumento essenziale per qualsiasi progetto di sviluppo, ma un aspetto in particolare potrebbe sovraccaricare il vostro workflow di codifica e distribuzione. Gli hook di Git permettono di creare script utilizzando diversi linguaggi per automatizzare vari aspetti del processo di controllo delle versioni. Si tratta di un concetto semplice con un retroterra un po’ complesso.

Il nostro post mostra come utilizzare tecniche avanzate per sfruttare al meglio i Git hooks. Potrete usarli sia localmente che lato server, renderli dinamici utilizzando parametri e variabili, lavorare con più repo remoti e molto altro ancora. A questo punto, possiamo arrivare a suggerire che i Git Hook potrebbero diventare la vostra arma segreta per aumentare la produttività, la qualità del codice e i tempi di realizzazione dei progetti.

Avete qualche domanda sui Git Hook e su come utilizzarli? Fatecelo sapere nella sezione commenti qui sotto!

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 ;).