¿Cómo agregar el nombre de la rama de Git al mensaje de confirmación?

103

Necesito ayuda con un script Bash que agregará automáticamente el nombre de la rama de git como un hash en los mensajes de confirmación.

Tomer Lichtash
fuente
3
Para cualquiera que venga aquí, parece que la mejor respuesta está al final de la página
Ben Taliadoros
Nota al margen: todo lo necesario git branch | grep ...para obtener la rama actual es la forma incorrecta de hacer esto. Considere git symbolic-ref -q HEAD(como se muestra en esta respuesta ) o git rev-parse --abbrev-ref HEAD. El comando symbolic-ref fallará si está en un HEAD separado, así que si desea detectar ese caso, úselo. De lo contrario, el método rev-parse --abbrev-ref es probablemente el mejor.
torek

Respuestas:

53

Utilice prepare-commit-msgo commit-msg githook .

Ya hay ejemplos en su PROJECT/.git/hooks/directorio.

Como medida de seguridad, tendrá que habilitar manualmente dicho gancho en cada repositorio que desee utilizar. Sin embargo, puede enviar el script y copiarlo en todos los clones en el .git/hooks/directorio.

ninjagecko
fuente
Gracias, una gran ventaja; gracias. Si pueden ayudarme más, con el guión en sí, estaré agradecido :)
Tomer Lichtash
5
No es necesario, ya tienes un ejemplo que hace exactamente lo que quieres , como ya dije, en .git/hooks/prepare-commit-msg.sample. =) Todo lo que necesita modificar (después de seguir las instrucciones en los comentarios) es copiar y pegar cualquier solución de stackoverflow.com/questions/1593051/… que
desee
4
@ninjagecko, para mí .git/hooks/prepare-commit-msg.samplecontiene tres ejemplos. Uno para comentar la sección de conflictos, agregar git diff --name-status -rresultados y agregar líneas firmadas por ... No se agrega el nombre de la rama al mensaje de confirmación. Así que me vi obligado a escribir mi propio gancho.
shytikov
1
¿ you will have to manually enable such a hook on each repository you wish to use itSignifica esto que debe otorgar permisos de ejecución al ARCHIVO? Si es así, ¿puedo editar la respuesta para incluirla (o usted, por favor)?
Dan Rosenstark
1
¿Por qué es esta la respuesta? Es más como déjame buscarlo en Google. La respuesta de @shytikov debe ser seleccionada
TheRealFakeNews
177

Aquí está mi commit-msgguión como ejemplo:

#!/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 el siguiente mensaje de confirmación:

[branch_name]: [original_message]

[branch_description]

Estoy usando el número de problema branch_name, ya que la descripción del problema se coloca en el comando branch_descriptionusing git branch --edit-description [branch_name].

Puede encontrar más información sobre las descripciones de las sucursales en esta sección de preguntas y respuestas .

El ejemplo de código se almacena en el siguiente Gist .

shytikov
fuente
8
Este script aplasta los mensajes de confirmación de varias líneas en una sola línea. Reemplacé tu declaración de eco con: echo -n "$ NAME" ':' | cat - "$ 1"> / tmp / out && mv / tmp / out "$ 1"
Alex Spence
4
Coloque este archivo en la carpeta PROJECT / .git / hooks /
catanore
2
Funciona bien. Pero para Mac, también tuve que configurar el permiso para que funcione: >>> sudo chmod 755 .git / hooks / commit-msg
Manoj Shrestha
1
@ManojShrestha sí, tiene que ser ejecutable
David Mann
2
@AlexSpence de forma más sencilla echo $NAME: "$(cat $1)" > $1. Esto funciona porque la razón por la que se perdieron las nuevas líneas es que echo estaba tratando cada línea de $(cat "$1")como un nuevo argumento y haciendo eco de cada una con un espacio entre ellas. Al rodear $(cat "$1")con comillas dobles, echo trata la salida del gato como un solo argumento. Además, no creo que sea necesario citar $1ya que su valor es.git/COMMIT_EDITMSG
PiersyP
30

Un script un poco más simple que agrega el nombre de la rama al mensaje de confirmación antes de editarlo. Entonces, si desea cambiarlo o eliminarlo, puede hacerlo.

Cree este archivo .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
Pylinux
fuente
4
Consigo: sed: 1: ".git/COMMIT_EDITMSG": invalid command code .al usar esto.
Adam Parkin
1
Ajá, diferencia de Mac OSX, consulte: hintsforums.macworld.com/showpost.php?p=393450&postcount=11 para la solución
Adam Parkin
2
como la verificación del caso de modificación y
reparación
3
OSX: necesita la extensión de archivo para funcionar si recibe el mensaje de error anterior. sed -i '.bak' "1s/^/$branchName : \n/" $1
canintex
Puede usarlo @como sedseparador en lugar de, /ya que es más probable que aparezcan barras diagonales en el nombre de la rama o en el mensaje de confirmación, arruinando sed.
Ory Band
28

Puede hacerlo con una combinación de los ganchos prepare-commit-msg y pre-commit.

.git / hooks / prepare-commit-msg

#!/bin/sh

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

.git / hooks / 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

Establecer permisos

sudo chmod 755 .git/hooks/prepare-commit-msg
sudo chmod 755 .git/hooks/pre-commit
Farid Movsumov
fuente
Tenga en cuenta que esto puede eliminar el mensaje de confirmación original si está utilizando, --amendpor ejemplo. En lugar de usar echo, debería usar seden su lugar. Aquí está en una sola línea:sed -i "1s@^@$(git branch | grep '^\*' | cut -b3-) @" $1
Ory Band
10

agregue el siguiente código en el archivo 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

Agregará el nombre de la rama para confirmar el mensaje, excepto merge-commit. El merge-commit tiene información de rama por defecto, por lo que un nombre de rama adicional es innecesario y hace que el mensaje sea feo.

Tim
fuente
1
Entonces, ¿esto no modificará el mensaje de confirmación cuando encuentre la palabra fusionar en el mensaje?
thoroc
1
@thoroc que es técnicamente correcto; sin embargo, en uso normal esto no es gran cosa. El mensaje de confirmación que se analiza son los "predeterminados" antes de editarlos. Así que mientras su plantilla de confirmación no tenga la palabra "fusionar", creo que debería estar bien (siempre y cuando los otros mensajes "predeterminados" no tengan la excepción de un mensaje de confirmación de fusión predeterminado). Originalmente entendí mal esto, y creo que lo tengo correcto ahora.
Novato C
5

Inspirado por la respuesta de Tim que se basa en la respuesta principal, resulta que el gancho prepare-commit-msg toma como argumento qué tipo de compromiso está ocurriendo . Como se ve en el prepare-commit-msg predeterminado, si $ 2 es 'fusionar', entonces es una confirmación de fusión. Por lo tanto, el cambio de mayúsculas y minúsculas se puede modificar para incluir la función addBranchName () de Tim.

He incluido mi propia preferencia sobre cómo agregar el nombre de la rama y todas las partes sin comentarios del prepare-commit-msg.samplegancho predeterminado .

prepare-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
Novato C
fuente
4

Si desea hacerlo global (para todos los proyectos):

Cree un git-msgarchivo con el contenido de la respuesta de shytikov y colóquelo en alguna carpeta:

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

Ahora habilite los ganchos:

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

y git initnuevamente en cada proyecto que desee utilizar.

Maroun
fuente
2
Descubrí que para usar esta función, tenía que poner 'commit-msg' en un directorio de 'hooks' dentro del directorio configurado para 'init.templatedir' para que cuando todo el templatedir se copie en 'git init', 'commit- msg 'termina en el directorio' .git / hooks 'del proyecto.
Dan
2

Estaba teniendo problemas para que estas soluciones funcionen en MacOS debido al hecho de que usa BSD en sedlugar de GNU sed. Sin embargo, logré crear un script simple que hace el trabajo. Todavía usando .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 

Esto supone un estándar de nomenclatura de ramas similar a functional-desc_JIRA-NUMBER. Si el nombre de su sucursal es solo su número de boleto de Jira, simplemente puede deshacerse de todo, desde la tubería hasta el f2. También requiere que tenga un archivo con nombre .gitmessageen su directorio personal.

PhPGuy
fuente
2

En caso de que desee que el ticket JIRA se agregue al mensaje de confirmación, utilice el siguiente script.

Confirme un mensaje como PROJECT-2313: Add awesome feature Esto requiere que el nombre de su sucursal comience con el Ticket de jira.

Esta es una combinación de estas soluciones:

Está modificado para OS X, con el sed -i '.bak'y funciona también desde 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
Mihai Georgescu
fuente
Esto funciona bien en el archivo del lado del cliente: prepare-commit-msg para rellenar automáticamente el prefijo de confirmación. Pero si quiero hacer lo mismo en el gancho del lado del servidor, que es el servidor bitbucket (en mi caso) y estoy tratando de agregar esta lógica en el gancho de pre-recepción en la ruta del servidor Bitbucket: BITBUCKET_HOME / shared / data / repositories / <repository-id> / hooks / 21_pre_receive, no funciona como "git symbolic-ref -q HEAD" dando 'master' aunque me estoy comprometiendo desde mi rama feature / abc del lado del cliente. ¿Hay otra forma aquí?
santhosh