Come aggiungere il nome del ramo di Git al messaggio di commit?


103

Ho bisogno di aiuto con uno script Bash che aggiungerà automaticamente il nome del ramo di git come hash nei messaggi di commit.


3
Per chiunque venga qui sembra che la risposta migliore sia in fondo alla pagina
Ben Taliadoros,

Nota a margine: tutto ciò git branch | grep ...per ottenere il ramo corrente è il modo sbagliato per farlo. Considera git symbolic-ref -q HEAD(come mostrato in questa risposta ) o git rev-parse --abbrev-ref HEAD. Il comando symbolic-ref fallirà se ti trovi su un HEAD distaccato, quindi se desideri rilevare quel caso, usalo. Altrimenti il ​​metodo rev-parse --abbrev-ref è probabilmente il migliore.
torek

Risposte:


53

Usa il prepare-commit-msgo commit-msg githook .

Ci sono esempi già nella tua PROJECT/.git/hooks/directory.

Come misura di sicurezza, dovrai abilitare manualmente tale hook su ogni repository che desideri usarlo. Tuttavia, puoi eseguire il commit dello script e copiarlo su tutti i cloni nella .git/hooks/directory.


Grazie un grande vantaggio; grazie. Se puoi aiutarmi ulteriormente, con lo script stesso, te ne sarò grato :)
Tomer Lichtash

5
Non ne ho bisogno, hai già un esempio che fa esattamente quello che vuoi , come ho già detto, in .git/hooks/prepare-commit-msg.sample. =) Tutto ciò che serve per modificare (dopo aver seguito le istruzioni nei commenti) è quello di copiare-incollare qualsiasi soluzione da stackoverflow.com/questions/1593051/... vuoi
ninjagecko

4
@ninjagecko, per me .git/hooks/prepare-commit-msg.samplecontiene tre esempi. Uno per commentare la sezione sui conflitti, aggiungervi git diff --name-status -routput e aggiungere righe Signed-off ... Non aggiungere il nome del ramo al messaggio di commit. Quindi sono stato costretto a scrivere il mio hook.
shytikov

1
Questo you will have to manually enable such a hook on each repository you wish to use itsignifica che devi dare al FILE i permessi di esecuzione? In tal caso, posso modificare la risposta per includerla (o potresti, per favore)?
Dan Rosenstark

1
Perché questa è la risposta? È più come lasciarmi google quello per te. La risposta di @shytikov dovrebbe essere selezionata
TheRealFakeNews

177

Ecco il mio commit-msgscript come esempio:

#!/bin/sh
#
# Automatically adds branch name and branch description to every commit message.
#
NAME=$(git branch | grep '*' | sed 's/* //') 
DESCRIPTION=$(git config branch."$NAME".description)

echo "$NAME"': '$(cat "$1") > "$1"
if [ -n "$DESCRIPTION" ] 
then
   echo "" >> "$1"
   echo $DESCRIPTION >> "$1"
fi 

Crea il seguente messaggio di commit:

[branch_name]: [original_message]

[branch_description]

Sto usando il numero del problema come branch_name, la descrizione del problema viene inserita nel comando branch_descriptionusing git branch --edit-description [branch_name].

Ulteriori informazioni sulle descrizioni delle filiali sono disponibili in questa sezione Domande e risposte .

L'esempio di codice è archiviato nel seguente Gist .


8
Questo script riduce i messaggi di commit a più righe su una singola riga. Ho sostituito la tua dichiarazione echo con: echo -n "$ NAME" ':' | cat - "$ 1"> / tmp / out && mv / tmp / out "$ 1"
Alex Spence

4
Metti questo file nella cartella PROJECT / .git / hooks /
catanore

2
Funziona bene. Ma per Mac, ho dovuto impostare anche l'autorizzazione per farlo funzionare: >>> sudo chmod 755 .git / hooks / commit-msg
Manoj Shrestha,

1
@ManojShrestha sì, deve essere eseguibile
David Mann

2
@AlexSpence più semplicemente potresti usare echo $NAME: "$(cat $1)" > $1. Questo funziona perché il motivo per cui le nuove righe venivano perse è che echo trattava ogni riga di $(cat "$1")come un nuovo argomento e riecheggiava ciascuna con uno spazio tra. Circondando $(cat "$1")tra virgolette, echo tratta l'output di cat come un singolo argomento. Inoltre non penso sia necessario citare $1poiché il suo valore è.git/COMMIT_EDITMSG
PiersyP

30

Uno script un po 'più semplice che aggiunge il nome del ramo al messaggio di commit prima di modificarlo. Quindi, se vuoi cambiarlo o rimuoverlo, puoi farlo.

Crea questo file .git / hooks / prepare-commit-msg :

#!/bin/bash

branchPath=$(git symbolic-ref -q HEAD) #Somthing like refs/heads/myBranchName
branchName=${branchPath##*/}      #Get text behind the last / of the branch path

firstLine=$(head -n1 $1)

if [ -z "$firstLine"  ] ;then #Check that this is not an amend by checking that the first line is empty
    sed -i "1s/^/$branchName: \n/" $1 #Insert branch name at the start of the commit message file
fi

4
Ottengo: sed: 1: ".git/COMMIT_EDITMSG": invalid command code .quando lo uso.
Adam Parkin

1
Ah, differenza Mac OSX, vedi: hintsforums.macworld.com/showpost.php?p=393450&postcount=11 per la correzione
Adam Parkin

2
come il controllo del caso di modifica e riparazione
pogopaule

3
OSX: richiede l'estensione del file per funzionare se ricevi il messaggio di errore sopra. sed -i '.bak' "1s/^/$branchName : \n/" $1
canintex

Puoi usarlo @come sedseparatore invece di /poiché è più probabile che le barre in avanti vengano visualizzate nel nome del ramo o nel messaggio di commit, rovinando tutto sed.
Ory Band

28

Puoi farlo con una combinazione degli hook prepare-commit-msg e pre-commit.

.git / ganci / preparare-commit-msg

#!/bin/sh

BRANCH=`git branch | grep '^\*' | cut -b3-`
FILE=`cat "$1"`
echo "$BRANCH $FILE" > "$1"

.git / ganci / pre-commit

#!/bin/bash

find vendor -name ".git*" -type d | while read i
do
        if [ -d "$i" ]; then
                DIR=`dirname $i`
                rm -fR $i
                git rm -r --cached $DIR > /dev/null 2>&1
                git add $DIR > /dev/null 2>&1
        fi
done

Imposta i permessi

sudo chmod 755 .git/hooks/prepare-commit-msg
sudo chmod 755 .git/hooks/pre-commit

Nota che questo può rimuovere il messaggio di commit originale se stai usando --amendad esempio. Invece di usare echodovresti usare sedinvece. Eccolo in una linea:sed -i "1s@^@$(git branch | grep '^\*' | cut -b3-) @" $1
Ory Band

10

aggiungi il codice seguente nel file prepare-commit-msg.

#!/bin/sh
#
# Automatically add branch name and branch description to every commit message except merge commit.
#

COMMIT_EDITMSG=$1

addBranchName() {
  NAME=$(git branch | grep '*' | sed 's/* //') 
  DESCRIPTION=$(git config branch."$NAME".description)
  echo "[$NAME]: $(cat $COMMIT_EDITMSG)" > $COMMIT_EDITMSG
  if [ -n "$DESCRIPTION" ] 
  then
     echo "" >> $COMMIT_EDITMSG
     echo $DESCRIPTION >> $COMMIT_EDITMSG
  fi 
}

MERGE=$(cat $COMMIT_EDITMSG|grep -i 'merge'|wc -l)

if [ $MERGE -eq 0 ] ; then
  addBranchName
fi

Aggiungerà il nome del ramo al messaggio di commit tranne il merge-commit. Il merge-commit ha informazioni sul ramo per impostazione predefinita, quindi il nome del ramo aggiuntivo non è necessario e rende il messaggio brutto.


1
Quindi questo non modificherà il messaggio di commit quando troverà la parola merge nel messaggio?
thoroc

1
@thoroc che è tecnicamente corretto; tuttavia, nell'uso normale questo non è un grosso problema. Il messaggio di commit che viene analizzato è quello "predefinito" prima di modificarli. Quindi fintanto che il tuo modello di commit non contiene la parola "merge", credo che dovresti essere a posto (a condizione che gli altri messaggi "predefiniti" non facciano eccezione per un messaggio di commit di merge predefinito). All'inizio ho frainteso questo e credo di averlo corretto ora.
Novice C

5

Ispirato dalla risposta di Tim che si basa sulla risposta principale, risulta che l'hook prepare-commit-msg prende come argomento il tipo di commit che si sta verificando . Come visto nel messaggio di default prepare-commit-msg, se $ 2 è 'merge' allora è un merge commit. Pertanto l'opzione case può essere modificata per includere la funzione addBranchName () di Tim.

Ho incluso la mia preferenza su come aggiungere il nome del ramo e tutte le parti non commentate prepare-commit-msg.sampledell'hook predefinito .

preparare-commit-msg

#!/bin/sh

addMyBranchName() {
  # Get name of current branch
  NAME=$(git branch | grep '*' | sed 's/* //')

  # First blank line is title, second is break for body, third is start of body
  BODY=`cut -d \| -f 6 $1 | grep -v -E .\+ -n | cut -d ':' -f1 | sed '3q;d'`

  # Put in string "(branch_name/): " at start of commit message body.
  # For templates with commit bodies
  if test ! -z $BODY; then
    awk 'NR=='$BODY'{$0="\('$NAME'/\): "}1;' $1 > tmp_msg && mv tmp_msg "$1"
  else
    echo "title\n\n($NAME/):\n`cat $1`\n" > "$1"
  fi
}

# You might need to consider squashes
case "$2,$3" in
  # Commits that already have a message
  commit,?*)
  ;;

  # Messages are one line messages you decide how to handle
  message,)
  ;;

  # Merge commits
  merge,)
    # Comments out the "Conflicts:" part of a merge commit.
    perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1"
  ;;

  # Non-merges with no prior messages
  *)
    addMyBranchName $1
  ;;
esac

4

Se vuoi renderlo globale (per tutti i progetti):

Crea un git-msgfile con il contenuto della risposta di shytikov e mettilo in una cartella:

mkdir -p ~/.git_hooks
# make it executable
chmod a+x ~/.git_hooks/commit-msg

Ora abilita gli hook:

git config --global init.templatedir '~/.git_hooks'

e git initancora in ogni progetto che vuoi usarlo.


2
Ho scoperto che per usare questa funzione, dovevo mettere 'commit-msg' in una directory 'hooks' all'interno della directory configurata per 'init.templatedir' in modo che quando l'intero templatedir viene copiato su 'git init', 'commit- msg 'finisce nella directory' .git / hooks 'del progetto.
Dan

2

Ho avuto problemi a far funzionare queste soluzioni su MacOS a causa del fatto che utilizza BSD sedinvece di GNU sed. Sono riuscito a creare un semplice script che fa il lavoro però. Ancora in uso .git/hooks/pre-commit:

#!/bin/sh
BRANCH=$(cat .git/HEAD  | cut -d '_' -f2)
if [ ! -z "$BRANCH" ]
then
    echo "$BRANCH" > "/Users/username/.gitmessage" 
else
    echo "[JIRA NUMBER]" > "/Users/username/.gitmessage"
fi 

Ciò presuppone uno standard di denominazione dei rami simile a functional-desc_JIRA-NUMBER. Se il nome della tua filiale è solo il numero del tuo biglietto Jira, puoi semplicemente sbarazzarti di tutto, dal tubo alla f2. Richiede anche che tu abbia un file denominato .gitmessagenella tua directory home.


2

Nel caso in cui desideri che il ticket JIRA venga aggiunto al messaggio di commit, utilizza lo script seguente.

Commit messaggio qualcosa di simile PROJECT-2313: Add awesome feature Questo richiede che il nome del tuo ramo inizi con il biglietto jira.

Questa è una combinazione di queste soluzioni:

È stato modificato per OS X, con sed -i '.bak'e funziona anche da SourceTree.

https://gist.github.com/georgescumihai/c368e199a9455807b9fbd66f44160095

#!/bin/sh
#
# A hook script to prepare the commit log message.
# If the branch name it's a jira Ticket.
# It adds the branch name to the commit message, if it is not already part of it.

branchPath=$(git symbolic-ref -q HEAD) #Somthing like refs/heads/myBranchName
branchName=${branchPath##*/}      #Get text behind the last / of the branch path

regex="(PROJECTNAME-[0-9]*)"

if [[ $branchName =~ $regex ]]
then
    # Get the captured portion of the branch name.
    jiraTicketName="${BASH_REMATCH[1]}"

    originalMessage=`cat $1`

    # If the message already begins with PROJECTNAME-#, do not edit the commit message.
    if [[ $originalMessage == $jiraTicketName* ]]
        then
        exit
    fi

    sed -i '.bak' "1s/^/$jiraTicketName: /" $1 #Insert branch name at the start of the commit message file
fi

Funziona bene sul file lato client: prepare-commit-msg per popolare automaticamente il prefisso del commit. Ma se voglio fare lo stesso sull'hook lato server, che è bitbucket server (nel mio caso) e sto cercando di aggiungere questa logica sull'hook di pre-ricezione nel percorso del server Bitbucket: BITBUCKET_HOME / shared / data / repository / <repository-id> / hooks / 21_pre_receive, non funziona come "git symbolic-ref -q HEAD" dando "master" sebbene io esegua il commit dal mio ramo feature / abc dal lato client. C'è un altro modo qui?
santhosh
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.