Gli script hook Git possono essere gestiti insieme al repository?


337

Vorremmo creare alcuni script hook di base che tutti possiamo condividere - per cose come i messaggi di commit pre-formattazione. Git ha script hook per quello che sono normalmente archiviati <project>/.git/hooks/. Tuttavia, tali script non vengono propagati quando le persone eseguono un clone e non sono controllate dalla versione.

C'è un buon modo per aiutare tutti a ottenere gli script hook corretti? Posso semplicemente fare in modo che quegli script hook puntino a script controllati dalla versione nel mio repository?


5
Una buona domanda Vorrei solo che ci fosse una risposta migliore (senza lamentele per @mipadi, vorrei solo che Git avesse un modo per farlo in modo più automatico - anche se solo con un'opzione specificata per git clone.)
lindes

Sono d'accordo, @lindes! Ma forse limitando questa condivisione di ami in modo intenzionale? Le cose sarebbero confuse per gli utenti Windows, suppongo.
kristianlm,

@kristianlm: Ci sono molte ragioni per cui a volte può essere disordinato ... e anche quando è bello averlo lì. Vorrei solo che ci fosse qualche opzione o qualcosa che potesse copiare i ganci. Immagino che dovrò controllare il codice git-core qualche volta e creare una patch. :) (O spero che qualcun altro lo faccia ... o convivi con la soluzione alternativa nella risposta di Mipadi , o qualsiasi altra cosa.)
partire il

pre-commitlo rende facile per gli hook pre-commit. Non risponde alla domanda dell'OP sulla gestione di alcun hook git arbitrario, ma gli hook pre-commit sono probabilmente i più frequentemente utilizzati per scopi di qualità del codice.
ericsoco,

Risposte:


144

In teoria, è possibile creare una hooksdirectory (o qualsiasi nome si preferisca) nella directory del progetto con tutti gli script, quindi collegarli in modo simbolico .git/hooks. Naturalmente, ogni persona che ha clonato il repository dovrebbe impostare questi collegamenti simbolici (anche se potresti essere davvero fantasioso e avere uno script di distribuzione che il clonatore potrebbe eseguire per configurarli in modo semi-automatico).

Per eseguire il collegamento simbolico su * nix, tutto ciò che devi fare è:

root="$(pwd)"
ln -s "$root/hooks" "$root/.git/hooks"

usa ln -sfse sei pronto a sovrascrivere cosa c'è dentro.git/hooks


38
questo non era banale, quindi includo un link su come eseguire il symlink in modo corretto: stackoverflow.com/questions/4592838/…
David T.

17
git versione 2.9 ora ha un'opzione di configurazione per core.hooksPathconfigurare un file esterno a .git per collegarsi alla cartella hooks.
Aaron Rabinowitz,

216

In Git 2.9 , l'opzione di configurazione core.hooksPathspecifica una directory di hook personalizzati.

Sposta i tuoi hook in una hooksdirectory tracciata nel tuo repository. Quindi, configurare ogni istanza del repository per utilizzare il tracciato hooksanziché $GIT_DIR/hooks:

git config core.hooksPath hooks

In generale, il percorso può essere assoluto o relativo alla directory in cui vengono eseguiti gli hook (in genere la radice dell'albero di lavoro; vedere la sezione DESCRIZIONE di man githooks).


15
... e la directory hook a cui puntare può essere un repository hook separato;)
René Link

10
Bene, questo parametro di configurazione è impostato automaticamente quando si esegue un clone git?
Anello il

4
Come regola generale, le variabili di configurazione non possono essere impostate dal repository che si sta clonando. Penso che questo sia per impedire l'esecuzione di codice arbitrario. git config controlla l'esecuzione del codice tramite hook, il nome utente sui messaggi di commit e altre importanti funzioni.
Max Shenfield,

1
Cosa succede se qualcuno nel team effettua un checkout git in un'altra filiale? Devono includerlo in ogni ramo ...
Jokerster,

1
È vero. D'altra parte, se si aggiornano gli hook nei commit più recenti, i repository clonati li otterranno automaticamente quando si lavora su rami creati sopra quel commit. Entrambe le vie hanno i loro lati positivi e negativi.
Fabb

15

Se il tuo progetto è un progetto JavaScript e usi npmcome gestore pacchetti puoi usare gitook condivisi per imporre githook npm install.


5
Ora so a chi sono state aggiunte quelle intrusioni .git/hooks.
gavenkoa,

Avviso: non supporta Windows (a meno che non sia eseguito come amministratore in git bash). La soluzione semplice è aggiungere "preinstall": "git config core.hooksPath hooks" come script in package.json. cioè dove hooks è una cartella che contiene i tuoi script git.
Shane Gannon,

8

Per gli utenti di Nodejs una soluzione semplice è aggiornare package.json con

{
  "name": "name",
  "version": "0.0.1",
  ......
  "scripts": {
    "preinstall": "git config core.hooksPath hooks", 

La preinstallazione verrà eseguita prima

npm install

e reindirizza git per cercare hook all'interno della directory. \ hooks (o con qualsiasi nome tu scelga). Questa directory dovrebbe imitare . \. Git \ hook in termini di nome del file (meno il .sample) e struttura.

Immagina che Maven e altri strumenti di costruzione avranno un equivalente alla preinstallazione .

Dovrebbe anche funzionare su tutte le piattaforme.

Se hai bisogno di ulteriori informazioni, consulta https://www.viget.com/articles/two-ways-to-share-git-hooks-with-your-team/


5

Che ne dici di git-hooks , instrada il .git/hooksrichiamo nello script nella directory del progetto githooks.

Ci sono anche molte funzioni che ti consentono di ridurre al minimo l'hook della copia e del collegamento simbolico.


5

La maggior parte dei moderni linguaggi di programmazione, o meglio i loro strumenti di compilazione, supportano i plugin per gestire i git hook. Ciò significa che tutto ciò che devi fare è configurare package.json, pom.xml, ecc., E chiunque nel tuo team non avrà altra scelta che conformarsi a meno che non modifichi il file di build. Il plugin aggiungerà contenuto alla directory .git per te.

Esempi:

https://github.com/rudikershaw/git-build-hook

https://github.com/olukyrich/githook-maven-plugin

https://www.npmjs.com/package/git-hooks


Ho cercato di farlo in modo generico, da utilizzare nei miei progetti, quindi ho scritto questo strumento: pypi.org/project/hooks4git
Lovato

3

Stiamo usando le soluzioni di Visual Studio (e quindi i progetti) che hanno eventi pre e post build. Sto aggiungendo un ulteriore progetto chiamato "GitHookDeployer". Il progetto modifica automaticamente un file nell'evento post build. Quel file è impostato per essere copiato nella directory di compilazione. Pertanto, il progetto viene creato ogni volta e non viene mai ignorato. Nell'evento build, si assicura anche che tutti gli hook git siano a posto.

Si noti che questa non è una soluzione generale, poiché alcuni progetti, ovviamente, non hanno nulla da costruire.


2

È possibile utilizzare una soluzione gestita per la gestione degli hook pre-commit come pre-commit . O una soluzione centralizzata per git-hooks lato server come Datree.io . Ha politiche integrate come:

  1. Rileva e previene l' unione di segreti .
  2. Applicare la corretta configurazione dell'utente Git .
  3. Imponi l' integrazione del ticket Jira - menziona il numero del ticket nel nome della richiesta pull / messaggio di commit.

Non sostituirà tutti i tuoi hook, ma potrebbe aiutare i tuoi sviluppatori con quelli più ovvi senza l'inferno di configurazione di installare i hook su ogni computer / repository di sviluppatori.

Disclaimer: sono uno dei fondatori di Datrees


1

Puoi rendere la tua cartella hooks un altro repository git e collegarlo come un sottomodulo ... Immagino ne valga la pena solo se hai molti membri e hook cambiati regolarmente.


1

Idealmente, gli hook vengono scritti in bash, se si seguono i file di esempio. Ma puoi scriverlo in qualsiasi lingua disponibile e assicurarti che abbia il flag eseguibile.

Quindi, puoi scrivere un codice Python o Go per raggiungere i tuoi obiettivi e posizionarlo nella cartella hook. Funzionerà, ma non sarà gestito insieme al repository.

Due opzioni

a) Script multipli

Puoi codificare i tuoi hook all'interno del tuo aiuto e aggiungere un piccolo frammento di codice agli hook, per chiamare il tuo script perfetto, in questo modo:

$ cat .git/hooks/pre-commit
#!/bin/bash
../../hooks/myprecommit.js

b) Script singolo

Un'opzione più interessante è quella di aggiungere solo uno script per governarli tutti, anziché diversi. Quindi, crei un hook / mysuperhook.go e punti ogni hook che vuoi avere.

$ cat .git/hooks/pre-commit
#!/bin/bash
../../hooks/mysuperhook.go $(basename $0)

Il parametro fornirà al tuo script quale hook è stato attivato e puoi differenziarlo all'interno del tuo codice. Perché? A volte potresti voler eseguire lo stesso controllo per commit e push, ad esempio.

E poi?

Quindi, potresti voler avere ulteriori funzionalità, come:

  • Attiva manualmente l'hook per verificare se tutto è ok anche prima di un commit o push. Se chiami semplicemente il tuo script (opzione a o b) farebbe il trucco.
  • Attiva gli hook su CI, quindi non è necessario riscrivere gli stessi controlli per CI, ad esempio sarebbe solo chiamare il commit e premere i grilletti. Lo stesso di quanto sopra dovrebbe risolverlo.
  • Chiama strumenti esterni, come un validatore markdown o un validatore YAML. Puoi creare syscall e devi gestire STDOUT e STDERR.
  • Assicurati che tutti gli sviluppatori abbiano un modo semplice per installare gli hook, quindi è necessario aggiungere uno script piacevole al repository per sostituire gli hook predefiniti con quelli corretti
  • Avere alcuni aiutanti globali, come un controllo per bloccare, si impegna a sviluppare e padroneggiare i rami, senza doverlo aggiungere a tutti i repository. Puoi risolverlo avendo un altro repository con script globali.

Questo può essere più semplice?

Sì, ci sono diversi strumenti per aiutarti a gestire git-hook. Ognuno di essi è progettato su misura per affrontare il problema da una prospettiva diversa e potrebbe essere necessario comprenderli tutti per ottenere quello che è meglio per te o il tuo team. GitHooks.com offre molte letture sull'aggancio e diversi strumenti disponibili oggi.

Ad oggi, ci sono 21 progetti elencati lì con diverse strategie per gestire git hook. Alcuni lo fanno solo per un singolo hook, altri per una lingua specifica e così via.

Uno di quegli strumenti, scritto da me e offerto gratuitamente come progetto opensource, si chiama hooks4git . È scritto in Python (perché mi piace) ma l'idea è quella di gestire tutti gli elementi sopra elencati in un singolo file di configurazione chiamato .hooks4git.ini, che vive all'interno del tuo repository e può chiamare qualsiasi script che desideri chiamare, in qualsiasi lingua .

L'uso dei git git è assolutamente fantastico, ma il modo in cui vengono offerti di solito allontana solo le persone.


Avevo pubblicato una versione molto più corta qualche tempo fa e, come concordato con i moderatori, questo porta spiegazioni al suo interno e un breve collegamento a uno strumento che ho scritto da solo, che penso possa aiutare altri sviluppatori.
Lovato,

1

Per gli utenti di livello

Ho trovato questi script molto utili per i progetti Gradle.

build.gradle

apply from: rootProject.file('gradle/install-git-hooks.gradle')

Gradle / install-git-hooks.gradle

tasks.create(name: 'gitExecutableHooks') {
    doLast {
        Runtime.getRuntime().exec("chmod -R +x .git/hooks/");
    }
}
task installGitHooks(type: Copy) {
    from new File(rootProject.rootDir, 'pre-commit')
    into { new File(rootProject.rootDir, '.git/hooks') }
}
gitExecutableHooks.dependsOn installGitHooks
clean.dependsOn gitExecutableHooks

pre-commit

.... your pre commit scripts goes here
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.