Come facilitare il flusso di lavoro di sviluppo del tuo team con Git Hooks
Pubblicato: 2022-03-10Uno dei requisiti principali per lavorare per un team o un progetto open source è l'utilizzo di un sistema di controllo della versione (VCS). Git è un sistema di controllo della versione distribuito gratuito e open source per tenere traccia delle modifiche al codice sorgente durante lo sviluppo del software. È stato creato da Linus Torvalds nel 2005 per lo sviluppo del kernel Linux. È facile da imparare e ha un ingombro minimo con prestazioni fulminee.
C'è una grande possibilità che tu abbia già utilizzato Git (dal momento che è uno degli strumenti VCS più popolari e ben adottati disponibili nella comunità di sviluppo) e molto probabilmente hai già una certa conoscenza dello staging e del commit del tuo codice spingendo e tirando da un repository remoto. Questo articolo non affronterà le basi dei flussi di lavoro git, ma si concentrerà principalmente sugli hook git e su come utilizzarli per ottenere una migliore collaborazione nel tuo team. Con i team che crescono di dimensioni, sta diventando ancora più importante mantenere i contributori in linea e mantenere regole diverse sul codice.
Cosa sono gli hook Git?
Gli hook Git sono script che vengono attivati quando vengono eseguite azioni o eventi specifici in un repository git. Queste azioni riguardano parti del flusso di lavoro di controllo della versione come il commit e il push. Gli hook possono essere davvero utili automatizzando le attività sul flusso di lavoro git. Ad esempio, possono aiutarci a convalidare la sintassi della nostra base di codice in base ad alcune regole specifiche o eseguire alcuni test prima di eseguire il commit delle modifiche.
Come farli impostare?
Gli hook Git sono una funzionalità integrata, il che significa che siamo in grado di accedervi e iniziare a usarli fintanto che un repository git è inizializzato. Diamo un'occhiata più in dettaglio cosa significa cercando di impostarli.
Usando il tuo terminale preferito, crea un nuovo repository git.
mkdir my-new-repository && cd my-new-repository git init ls -la
Noterai che è stata appena creata una nuova directory nascosta. Questa cartella .git
viene utilizzata da git per memorizzare informazioni relative al repository, come hash di controllo della versione, informazioni sui commit, indirizzi di repository remoti e così via. Questa è anche la cartella in cui gli hook risiedono effettivamente per git .git/hooks
. È possibile trovare alcuni script di esempio precompilati creati automaticamente durante l'inizializzazione. Questi sono in realtà gli script che verranno attivati dopo azioni specifiche.
ls .git/hooks
Alcuni dei campioni che puoi trovare sono:
-
pre-commit.sample
: invocato appena prima di eseguire il commit. -
commit-msg.sample
: modifica il file di messaggio sul posto. -
post-receive.sample
: invocato dopo l'aggiornamento del repository remoto.
Sotto il cappuccio
Ora che sappiamo dove possiamo trovare gli hook, facciamo un passo indietro per capire come funzionano effettivamente.
Gli hook Git sono basati sugli eventi, quindi finché eseguiamo un comando git nel flusso di sviluppo, git controllerà le cartelle degli hook per trovare se è presente uno script associato da eseguire. Alcuni di questi script verranno eseguiti prima o dopo queste azioni del flusso di sviluppo.
Un buon esempio per noi da esaminare e comprendere in modo più specifico il flusso in cui vengono attivati gli hook è il flusso di lavoro di commit, che è un caso d'uso abbastanza familiare.
Ogni volta che eseguiamo il commit di modifiche alla nostra base di codice, alcuni di questi hook correlati vengono attivati nel seguente ordine:
-
pre-commit
: ispeziona lo snapshot che sta per essere sottoposto a commit e verifica cosa deve essere commit. -
prepare-commit-msg
: ti consente di modificare il messaggio predefinito prima che l'autore del commit lo veda. -
commit-msg
: imposta il messaggio di commit su un modello. -
post-commit
: esegue un'azione subito dopo il completamento del commit e invia ad esempio una notifica.
Nel repository di cui sopra, proviamo ora ad aggiungere alcuni script pre e post commit personalizzati per visualizzare ulteriormente come funzionano effettivamente gli hook di git.
nano .git/hooks/pre-commit
Aggiungi il seguente frammento:
#!/bin/sh echo Changes are about to be committed
Assicurati che i nostri script siano eseguibili:
chmod +x .git/hooks/pre-commit
Ripetere la procedura precedente per lo script post-commit
:
nano .git/hooks/post-commit
#!/bin/sh echo Changes have been committed
chmod +x .git/hooks/post-commit
Ora possiamo aggiungere un nuovo file nano index.html
con un piccolo snippet HTML solo a scopo dimostrativo (non c'è bisogno che i validatori HTML lo sappiano).
<h1>Hello world from our new repository!</h1>
Aggiungeremo le modifiche alla nostra base di codice attraverso lo staging e quindi commetteremo questo:
git add . git commit
Dopo che il commit è stato elaborato con successo, possiamo vedere il seguente output dei due script sopra aggiunti:
Changes are about to be committed Changes have been committed
Come previsto, git ha attivato hook nel flusso di commit. Gli script pre-commit
e post-commit
che sono stati aggiunti sono in esecuzione e verranno eseguiti nella sequenza corretta (in base all'ordine menzionato in precedenza).
Questa è stata una semplice dimostrazione per capire come funzionano gli script del flusso di lavoro di commit e come vengono eseguiti. Per maggiori dettagli su questo flusso di lavoro, puoi leggere di più nella documentazione.
Nell'esempio sopra, abbiamo scelto di scrivere questi due script in bash, ma la verità è che git supporta hook che possono essere scritti in qualsiasi linguaggio di scripting desideriamo. Ruby, Python o JavaScript sono ottime alternative, purché impostiamo lo shebang corretto nella prima riga del nostro script eseguibile.
Ad esempio, possiamo riscrivere l'hook pre-commit
come uno script Node.js come di seguito:
#!/usr/bin/env node console.log("Changes are about to be commited")
Hook locali e remoti
Gli hook sono separati tra locale e remoto (o client e server). Mentre gli hook locali vengono eseguiti prima o dopo azioni specifiche sul repository locale, gli hook remoti vengono eseguiti prima o dopo i push al server. Quelli locali non possono essere utilizzati per far rispettare le politiche poiché la loro natura consente agli sviluppatori di modificarle facilmente. Sono utilizzati principalmente per attenersi ad alcune linee guida specifiche che vogliamo applicare all'interno di un team. Nel caso in cui desideriamo essere più severi e applicare alcune politiche per il nostro repository, risiediamo in hook remoti.
Ganci locali
-
pre-commit
-
prepare-commit-msg
-
commit-msg
-
post-commit
-
applypatch-msg
-
pre-applypatch
-
post-applypatch
-
pre-rebase
-
post-rewrite
-
post-checkout
-
post-merge
-
pre-push
Ganci remoti
-
pre-receive
-
update
-
post-receive
Condivisione di ganci
Gli hook Git si basano sulla loro condivisione all'interno del team. Questo è il motivo principale per cui esistono: promuovere una migliore collaborazione in team, automatizzare i processi dannosi e permetterci di concentrarci solo sulle parti importanti della base di codice.
Come affermato in precedenza, .git/hooks
è la cartella che ospita i nostri hook personalizzati, ma questo non è molto utile quando dobbiamo condividere questi script all'interno del team poiché questa cartella non è tracciata da git.
Un buon approccio per risolvere questo problema è aggiungere tutti i nostri hook personalizzati in una cartella separata all'interno del nostro repository. Ad esempio, possiamo aggiungere una cartella .githooks
e salvare lì gli script eseguibili. Quindi, all'inizializzazione del progetto, possiamo copiare esplicitamente o collegare simbolicamente questi script alla cartella originale per mantenere i nostri hooks .git/hooks
.
find .git/hooks -type l -exec rm {} \\; find .githooks -type f -exec ln -sf ../../{} .git/hooks/ \\;
In alternativa, se stai utilizzando l'ultima versione di git (parlando di 2.9
e versioni successive) siamo in grado di configurare direttamente il percorso di git hooks nella nostra cartella personalizzata:
git config core.hooksPath .githooks
Git Hooks Made Easy (un caso d'uso di codebase JavaScript)
Esistono strumenti che ci aiutano a integrare ulteriormente gli hook git con le esigenze della nostra base di codice. In particolare per le basi di codice JavaScript, c'è Husky con il quale possiamo facilmente personalizzare le azioni sugli eventi git tramite la configurazione.
Ad esempio, possiamo facilmente eseguire il lint del nostro codice o eseguire alcuni test nell'evento pre-commit
e procedere al commit in base al fatto che il linting, il test o entrambi abbiano esito positivo o meno.
Questo può essere ottenuto estendendo la configurazione package.json
semplicemente come:
{ "scripts": { "test": "echo Running tests" }, "devDependencies": { "eslint": "5.16.0", }, "husky": { "hooks": { "pre-commit": "eslint . && npm test", } } }
Conclusione
In questo articolo, abbiamo scoperto che diverse azioni intraprese su un repository git possono facoltativamente attivare l'esecuzione di script personalizzati. Tali script possono essere sotto il controllo dello sviluppatore in locale o gestiti in modo più centralizzato per un team o un progetto in remoto. Abbiamo anche appreso che gli script sono spesso scritti in uno script di shell come bash, ma in realtà possono utilizzare quasi tutti i linguaggi di scripting, anche JavaScript.
Gli hook Git possono essere una parte davvero potente di un flusso di lavoro ben progettato e ti incoraggio a provarli e vedere cosa puoi fare per i tuoi progetti.