Mettere git hook nel repository


197

È considerato una cattiva pratica - inserire .git / hook nel repository dei progetti (usando ad esempio i collegamenti simbolici). Se sì, qual è il modo migliore per fornire gli stessi hook a diversi utenti Git?

Risposte:


143

In genere sono d'accordo con Scytale, con un paio di suggerimenti aggiuntivi, abbastanza da meritare una risposta separata.

Innanzitutto, è necessario scrivere uno script che crei i collegamenti simbolici appropriati, soprattutto se questi hook riguardano l'applicazione della politica o la creazione di notifiche utili. Le persone avranno molte più probabilità di usare gli hook se possono semplicemente digitare bin/create-hook-symlinksche se devono farlo da soli.

In secondo luogo, i hook di collegamento simbolico diretto impediscono agli utenti di aggiungere i propri hook personali. Ad esempio, mi piace piuttosto l'hook pre-commit di esempio che assicura che non ci siano errori di spazi bianchi. Un ottimo modo per aggirare questo problema è inserire uno script wrapper nel repository e collegare simbolicamente tutti gli hook ad esso. Il wrapper può quindi esaminare $0(supponendo che sia uno script bash; un equivalente come argv[0]altrimenti) per capire quale hook è stato invocato come, quindi invocare l'hook appropriato all'interno del repository, nonché l'hook dell'utente appropriato, che dovrà essere rinominato , passando tutti gli argomenti a ciascuno. Esempio rapido dalla memoria:

#!/bin/bash
if [ -x $0.local ]; then
    $0.local "$@" || exit $?
fi
if [ -x tracked_hooks/$(basename $0) ]; then
    tracked_hooks/$(basename $0) "$@" || exit $?
fi

Lo script di installazione sposta tutti gli hook preesistenti sul lato (aggiungi i .localloro nomi) e collega simbolicamente tutti i nomi di hook noti allo script precedente:

#!/bin/bash
HOOK_NAMES="applypatch-msg pre-applypatch post-applypatch pre-commit prepare-commit-msg commit-msg post-commit pre-rebase post-checkout post-merge pre-receive update post-receive post-update pre-auto-gc"
# assuming the script is in a bin directory, one level into the repo
HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks

for hook in $HOOK_NAMES; do
    # If the hook already exists, is executable, and is not a symlink
    if [ ! -h $HOOK_DIR/$hook -a -x $HOOK_DIR/$hook ]; then
        mv $HOOK_DIR/$hook $HOOK_DIR/$hook.local
    fi
    # create the symlink, overwriting the file if it exists
    # probably the only way this would happen is if you're using an old version of git
    # -- back when the sample hooks were not executable, instead of being named ____.sample
    ln -s -f ../../bin/hooks-wrapper $HOOK_DIR/$hook
done

6
Ho aggiunto chmod +x .git/hooks/*a te bin/create-hook-symlinks per farlo funzionare.
guneiso

6
@guneysus Non dovresti averne bisogno, perché gli hook dovrebbero essere già eseguibili (dovrebbero essere controllati in quel modo) ei link non hanno bisogno di autorizzazioni speciali, ma solo dei file a cui si collegano.
Cascabel,

13
Un modo migliore per ottenere la directory hook è HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks.
Arnold Daniels,

2
Ho creato un semplice sistema basato su questo per gestire gli hook nel mio progetto: ell.io/tt$Paws.js/blob/Master/Scripts/install-git-hooks.sh
ELLIOTTCABLE

6
Ho preso solo l'essenziale e l'ho messo in un repository github.com/sjungwirth/githooks
Scott Jungwirth,

111

No, inserirli nel repository va bene, suggerirei anche di farlo (se sono utili anche per gli altri). L'utente deve abilitarli esplicitamente (come hai detto, ad esempio tramite collegamento simbolico), che da un lato è un po 'una seccatura, ma dall'altro protegge gli utenti dall'esecuzione di codice arbitrario senza il loro consenso.


13
cosa succede se si tratta di una politica aziendale, quindi il codice non è "arbitrario", questo è il codice richiesto, quindi questo sarebbe considerato una limitazione in GIT, per non avere un'altra directory (predefinita), che viene tracciata, che ottiene anche eseguito insieme ai ganci regolari
Tobias Hagenbeek,

14
Fornire automaticamente hook è un problema di sicurezza, sono contento che Git non lo faccia direttamente - per applicare i criteri di team / società, utilizzare hook sul lato server o consentire agli utenti di decidere manualmente di abilitarli come descritto da @scy :)
Mark K Cowan,

4
"protegge gli utenti [...] dall'esecuzione di codice arbitrario senza il loro consenso". Se uno sviluppatore dovesse fare il tuo suggerimento (collegamento simbolico), l'hook potrebbe essere modificato da qualcun altro ed eseguire "codice arbitrario senza il suo consenso"
MiniGod

24
MiniGod: certo. Se sei sufficientemente paranoico, puoi copiare i ganci invece di collegarli simbolicamente, quindi controllarli e solo successivamente abilitarli. Tuttavia, la maggior parte dei repository Git (citazione necessaria) conterrà il codice sorgente che deve essere eseguito sul computer dell'utente, quindi è probabile che tu esegua comunque un codice non verificato in costante cambiamento. Ma sì, hai ragione. ;)
scy

46

Al giorno d'oggi è possibile effettuare le seguenti operazioni per impostare una directory che è sotto il controllo di versione per essere la vostra directory di ganci git, per esempio, MY_REPO_DIR/.githookssarebbe

git config --local core.hooksPath .githooks/

Ancora non direttamente applicabile ma, se aggiungi una nota nel tuo README (o qualsiasi altra cosa), ciò richiede un minimo sforzo da parte di ogni sviluppatore.


3
Un trucco che ho trovato su viget.com/articles/two-ways-to-share-git-hooks-with-your-team è quello di impostare l'opzione dal tuo Makefile / CMake config / qualunque cosa.
Julius Bullinger

6

Da http://git-scm.com/docs/git-init#_template_directory , è possibile utilizzare uno di questi meccanismi per aggiornare la directory .git / hooks di ogni repository git appena creato:

La directory del modello contiene file e directory che verranno copiati in $ GIT_DIR dopo la sua creazione.

La directory dei template sarà una delle seguenti (in ordine):

  • l'argomento fornito con l'opzione --template;

  • il contenuto della variabile d'ambiente $ GIT_TEMPLATE_DIR;

  • la variabile di configurazione init.templateDir; o

  • la directory dei template predefinita: / usr / share / git-core / templates.


5

Archivia nel progetto e installa nella build

Come altri affermano nella loro risposta, se i tuoi hook sono specifici per i tuoi progetti particolari, includili nel progetto stesso, gestito da git. Vorrei proseguire ulteriormente e dire che, dato che è buona prassi far costruire il progetto usando un singolo script o comando, i hook devono essere installati durante la compilazione.

Ho scritto un articolo su gestione degli hook git , se sei interessato a leggere questo argomento in modo un po 'più approfondito.

Java e Maven

Dichiarazione di non responsabilità completa; Ho scritto il plugin Maven descritto di seguito.

Se stai gestendo la gestione build con Maven per i tuoi progetti Java, il seguente plug-in Maven gestisce l'installazione di hook da una posizione nel tuo progetto.

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

Metti tutti i tuoi hook Git in una directory nel tuo progetto, quindi configura il tuo pom.xmlper includere la seguente dichiarazione, obiettivo e configurazione del plugin.

<build>
  <plugins>
    <plugin>
      <groupId>com.rudikershaw.gitbuildhook</groupId>
      <artifactId>git-build-hook-maven-plugin</artifactId>
      <configuration>
        <gitConfig>
          <!-- The location of the directory you are using to store the Git hooks in your project. -->
          <core.hooksPath>hooks-directory/</core.hooksPath>
        </gitConfig>
      </configuration>
      <executions>
        <execution>
          <goals>       
            <!-- Sets git config specified under configuration > gitConfig. -->
            <goal>configure</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
      <!-- ... etc ... -->
  </plugins>
</build>

Quando esegui la compilazione del tuo progetto, il plugin configurerà git per eseguire hook dalla directory specificata. Questo imposterà efficacemente gli hook in quella directory per tutti coloro che lavorano al tuo progetto.

JavaScript e NPM

Per NPM esiste una dipendenza chiamata Husky che consente di installare hook inclusi quelli scritti in JavaScript.

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "npm test",
      "pre-push": "npm test",
      "...": "..."
    }
  }
}

Altri

Inoltre, ci sono pre-commit per progetti Python, progetti Overcommit per Ruby e progetti Lefthook per Ruby o Node.


1
Grazie per aver creato questo plugin, mi ha facilitato l'integrazione del mio file pre-commit.
Michiel Bugher


1

Ecco uno script, add-git-hook.sh, che puoi spedire come un normale file nel repository e può essere eseguito per aggiungere l'hook git al file di script. Regola quale hook utilizzare (pre-commit, post-commit, pre-push, ecc.) E la definizione di hook nell'eredità del gatto.

#!/usr/bin/bash
# Adds the git-hook described below. Appends to the hook file
# if it already exists or creates the file if it does not.
# Note: CWD must be inside target repository

HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks
HOOK_FILE="$HOOK_DIR"/post-commit

# Create script file if doesn't exist
if [ ! -e "$HOOK_FILE" ] ; then
        echo '#!/usr/bin/bash' >> "$HOOK_FILE"
        chmod 700 "$HOOK_FILE"
fi

# Append hook code into script
cat >> "$HOOK_FILE" <<EOF

########################################
# ... post-commit hook script here ... #
########################################

EOF

Questo script potrebbe avere senso avere autorizzazioni eseguibili o l'utente può eseguirlo direttamente. Ho usato questo per git-pull automatico su altre macchine dopo che mi sono impegnato.

EDIT-- Ho risposto alla domanda più semplice che non era quello che era stato chiesto e non era quello che l'OP stava cercando. Ho commentato i casi d'uso e gli argomenti per la spedizione di script hook nel repository rispetto a gestirli esternamente nei commenti qui sotto. Spero che sia quello che stai cercando.


Apprezzo il tuo impegno e credo che qui ci siano informazioni preziose, che non rispondono alla domanda dichiarata.
shabunc,

A mio avviso, se gli hook sono specifici di un determinato repository o sono componenti integrali dei flussi di lavoro utilizzati, appartengono al repository come file. È difficile metterli altrove senza creare più problemi di quanti ne risolva. È possibile archiviare hook generali in un repository proprio o su un'unità condivisa che potrebbe mantenere il repository del progetto perfettamente pulito ma a costo di essere molto meno pratico. Concordo con gli altri utenti nel dire che gli hook devono essere facili da aggiungere. I collegamenti simbolici possono creare inutili dipendenze da un particolare sistema o struttura di file.
mathewguest,

Inoltre, i collegamenti simbolici interrompono la capacità degli utenti di aggiungere i propri hook. La directory .git / hooks non viene tracciata, quindi l'origine dovrebbe iniziare nel repository e inserirsi nello script hooks, non viceversa. Penso che la controargomentazione sarebbe che gli hook git sono più legati al flusso di lavoro o al team piuttosto che al progetto e quindi non appartengono al repository. A seconda del tuo caso d'uso specifico, sei più a tuo agio nel inquinare potenzialmente il repository git con hook meno correlati o preferiresti rinunciare a un sacco di complessità nel metterli altrove?
mathewguest,

1

Per i progetti PHP basati su Composer è possibile distribuire automaticamente agli ingegneri. Ecco un esempio di hook pre-commit e commit-msg.

Crea una hookscartella, quindi nel tuo composer.json:

 },
 "scripts": {
     "post-install-cmd": [
         "cp -r 'hooks/' '.git/hooks/'",
         "php -r \"copy('hooks/pre-commit', '.git/hooks/pre-commit');\"",
         "php -r \"copy('hooks/commit-msg', '.git/hooks/commit-msg');\"",
         "php -r \"chmod('.git/hooks/pre-commit', 0777);\"",
         "php -r \"chmod('.git/hooks/commit-msg', 0777);\"",
     ],

Quindi puoi anche aggiornarli mentre il progetto continua mentre tutti sono in esecuzione composer installsu base regolare.


0

È possibile utilizzare una soluzione gestita per la gestione 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


3
Penso che stai realizzando un prodotto interessante, ma penso anche che questo non risponda alla domanda e fondamentalmente sia un'autopromozione e niente di più.
shabunc,
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.