Utilizzando il gancio aggiornamento
Sai di ganci - Si prega di leggere il documentation su di loro! L'hook che vorresti è l'aggiornamento, che viene eseguito una volta per ref. (Il gancio di pre-ricezione viene eseguito una volta per l'intera spinta) Ci sono tonnellate e tonnellate di domande e risposte su questi ganci già su SO; a seconda di cosa vuoi fare, puoi probabilmente trovare indicazioni su come scrivere il gancio se ne hai bisogno.
a sottolineare che questo è davvero possibile, una citazione dalla documentazione:
Questo gancio può essere usato per prevenire l'aggiornamento forzato su alcuni refs facendo in modo che il nome dell'oggetto è un oggetto commit che è un discendente dell'oggetto commit nominato dal vecchio nome dell'oggetto. Vale a dire, per applicare una politica di "solo avanzamento rapido".
Può anche essere utilizzato per registrare il vecchio stato ... nuovo.
E specificità:
Il gancio eseguita una volta per ogni ref essere aggiornato, e richiede tre parametri:
- il nome del ref fase di aggiornamento,
- la nome dell'oggetto vecchio memorizzato nel riferimento
- e il nuovo nome oggetto da memorizzare nel rif.
Così, per esempio, se si vuole fare in modo che nessuno dei soggetti di commit sono più lungo di 80 caratteri, un'implementazione molto rudimentale sarebbe:
#!/bin/bash
long_subject=$(git log --pretty=%s $2..$3 | egrep -m 1 '.{81}')
if [ -n "$long_subject" ]; then
echo "error: commit subject over 80 characters:"
echo " $long_subject"
exit 1
fi
Naturalmente, questo è un esempio di giocattolo; nel caso generale, dovresti utilizzare un output di registro contenente il messaggio di commit completo, dividerlo per commit e chiamare il tuo codice di verifica su ogni singolo messaggio di commit.
Perché si desidera che il gancio di aggiornamento
Questo è stato discusso/chiarito nei commenti; ecco un riassunto.
Il gancio di aggiornamento viene eseguito una volta per ref. Un riferimento è un puntatore a un oggetto; in questo caso, stiamo parlando di rami e tag, e in genere solo di diramazioni (le persone non spingono spesso i tag, dato che di solito si limitano a contrassegnare le versioni).
Ora, se un utente sta spingendo gli aggiornamenti di due rami, maestro e sperimentale:
o - o - o (origin/master) - o - X - o - o (master)
\
o - o (origin/experimental) - o - o (experimental)
Supponiamo che X è il "cattivo" commit, vale a dire quella che verrebbe a mancare il gancio commit-msg. Chiaramente non vogliamo accettare la spinta da padroneggiare. Quindi, l'hook di aggiornamento lo rifiuta. Ma non c'è niente di sbagliato con i commit su experimental! Il gancio di aggiornamento accetta quello. Pertanto, origin/master rimane invariato, ma di origine/sperimentale viene aggiornato:
o - o - o (origin/master) - o - X - o - o (master)
\
o - o - o - o (origin/experimental, experimental)
Il pre-ricezione gancio viene eseguito solo una volta, proprio prima di iniziare a aggiornare arbitri (prima della prima volta che si esegue il gancio di aggiornamento). Se lo avessi usato, avresti dovuto far fallire l'intera spinta, dicendo che poiché c'era un messaggio di commit errato sul master, in qualche modo non ti fidi più che i commit su experimental siano buoni anche se i loro messaggi sono a posto!
Penso che l'hook che l'OP sta cercando sia pre-ricevuto, dal momento che lui/lei vuole rifiutare l'intero push a seconda del messaggio di commit. Tuttavia, AFAIK, né pre-ricezione né aggiornamento ricevono il messaggio di commit come input. Quindi usare commit-msg sarà probabilmente la soluzione migliore. –
@ Can: Sono abbastanza sicuro che l'OP vuole aggiornare, non pre-ricevere. "L'intera spinta" significa la spinta per tutti i rami. Se l'utente tenta di inviare aggiornamenti a tre rami e solo uno contiene messaggi di commit non validi, gli altri due devono ancora essere accettati! – Cascabel
@ Can: E no, il messaggio di commit non fa parte dell'input, ma i nomi dei vecchi e nuovi oggetti (commit) (SHA1s) lo sono. Si noti che il hook di aggiornamento viene eseguito subito prima dell'aggiornamento dei riferimenti (dopo che gli oggetti commit sono stati ricevuti). L'hook può quindi utilizzare git log per ispezionare qualsiasi cosa voglia sui commit tra vecchio e nuovo, inclusi i loro messaggi di commit. – Cascabel