Wie füge ich den Git-Filialnamen zur Commit-Nachricht hinzu?

102

Ich benötige Hilfe bei einem Bash-Skript, das automatisch den Zweignamen des Git als Hash in Commit-Nachrichten hinzufügt.

Tomer Lichtash
quelle
3
Für jeden, der hierher kommt, scheint die beste Antwort am Ende der Seite zu sein
Ben Taliadoros
Randnotiz: Alle git branch | grep ..., um den aktuellen Zweig zu erhalten, sind der falsche Weg, dies zu tun. Betrachten Sie entweder git symbolic-ref -q HEAD(wie in dieser Antwort gezeigt ) oder git rev-parse --abbrev-ref HEAD. Der Befehl symbolic-ref schlägt fehl, wenn Sie sich auf einem getrennten HEAD befinden. Wenn Sie diesen Fall erkennen möchten, verwenden Sie ihn. Andernfalls ist die Methode rev-parse --abbrev-ref wahrscheinlich am besten.
Torek

Antworten:

53

Verwenden Sie den prepare-commit-msgoder commit-msg Githook .

In Ihrem PROJECT/.git/hooks/Verzeichnis befinden sich bereits Beispiele .

Aus Sicherheitsgründen müssen Sie einen solchen Hook für jedes Repository, das Sie verwenden möchten, manuell aktivieren. Sie können das Skript jedoch festschreiben und auf alle Klone in das .git/hooks/Verzeichnis kopieren .

Ninjagecko
quelle
Vielen Dank für einen tollen Hinweis; Danke. Wenn Sie mir mit dem Skript selbst weiter helfen können, bin ich Ihnen dankbar :)
Tomer Lichtash
5
Ich brauche nicht, Sie haben bereits ein Beispiel, das genau das tut , was Sie wollen , wie ich bereits sagte .git/hooks/prepare-commit-msg.sample. =) Alles, was Sie ändern müssen (nachdem Sie den Anweisungen in den Kommentaren gefolgt sind ), ist das Kopieren und Einfügen einer beliebigen Lösung von stackoverflow.com/questions/1593051/…, die Sie
möchten
4
@ninjagecko, .git/hooks/prepare-commit-msg.sampleenthält für mich drei Beispiele. Eine zum Auskommentieren von Konflikten, zum Hinzufügen von git diff --name-status -rAusgaben und zum Hinzufügen von abgemeldeten Zeilen ... Kein Hinzufügen eines Zweigstellennamens zur Festschreibungsnachricht. Also musste ich meinen eigenen Hook schreiben.
Shytikov
1
Bedeutet dies you will have to manually enable such a hook on each repository you wish to use it, dass Sie der DATEI Ausführungsberechtigungen erteilen müssen? Wenn ja, darf ich die Antwort so bearbeiten, dass sie dies enthält (oder könnten Sie bitte)?
Dan Rosenstark
1
Warum ist das die Antwort? Es ist eher so, als würde ich das für Sie googeln. Antwort von @shytikov sollte ausgewählt werden
TheRealFakeNews
177

Hier ist mein commit-msgSkript als Beispiel:

#!/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 

Erstellt die folgende Festschreibungsnachricht:

[branch_name]: [original_message]

[branch_description]

Ich verwende die Ausgabenummer als branch_name, die Problembeschreibung wird in den Befehl branch_descriptionusing git branch --edit-description [branch_name]eingefügt.

Weitere Informationen zu Branchenbeschreibungen finden Sie in diesen Fragen und Antworten .

Das Codebeispiel ist in der folgenden Übersicht gespeichert .

shytikov
quelle
8
Dieses Skript drückt mehrzeilige Festschreibungsnachrichten auf eine einzelne Zeile. Ich habe Ihre Echo-Anweisung ersetzt durch: echo -n "$ NAME" ':' | cat - "$ 1"> / tmp / out && mv / tmp / out "$ 1"
Alex Spence
4
Legen Sie diese Datei in den Ordner PROJECT / .git / hooks /
catanore
2
Es funktioniert gut. Aber für Mac musste ich auch die Erlaubnis festlegen, damit es funktioniert: >>> sudo chmod 755 .git / hooks / commit-msg
Manoj Shrestha
1
@ManojShrestha ja, es muss ausführbar sein
David Mann
2
@AlexSpence einfacher könnte man verwenden echo $NAME: "$(cat $1)" > $1. Dies funktioniert, weil der Grund dafür, dass die Zeilenumbrüche verloren gingen, darin besteht, dass das Echo jede Zeile $(cat "$1")als neues Argument behandelt und jedes mit einem Leerzeichen dazwischen wiedergibt . Durch das Umgeben $(cat "$1")mit doppelten Anführungszeichen behandelt echo die Cat-Ausgabe als ein einziges Argument. Ich denke auch nicht, dass es notwendig ist zu zitieren, $1da sein Wert ist.git/COMMIT_EDITMSG
PiersyP
30

Ein etwas einfacheres Skript, das den Zweignamen zur Festschreibungsnachricht hinzufügt, bevor Sie sie bearbeiten. Wenn Sie es also ändern oder entfernen möchten, können Sie dies tun.

Erstellen Sie diese Datei .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
quelle
4
Ich verstehe: sed: 1: ".git/COMMIT_EDITMSG": invalid command code .wenn ich das benutze.
Adam Parkin
1
Aha, Mac OSX Unterschied, siehe: hintsforums.macworld.com/showpost.php?p=393450&postcount=11 für das Update
Adam Parkin
2
wie die Überprüfung des Änderungs- und Korrekturfalls
Pogopaule
3
OSX: Benötigt eine Dateierweiterung, wenn die obige Fehlermeldung angezeigt wird. sed -i '.bak' "1s/^/$branchName : \n/" $1
Canintex
Sie können es auch @als sedTrennzeichen verwenden, /da Schrägstriche eher im Filialnamen oder in der Festschreibungsnachricht angezeigt werden sed.
Ory Band
28

Sie können dies mit einer Kombination aus den Hooks prepare-commit-msg und pre-commit tun.

.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

Berechtigungen festlegen

sudo chmod 755 .git/hooks/prepare-commit-msg
sudo chmod 755 .git/hooks/pre-commit
Farid Movsumov
quelle
Beachten Sie, dass dadurch die ursprüngliche Festschreibungsnachricht entfernt werden kann, wenn Sie --amendbeispielsweise verwenden. Anstatt zu verwenden echo, sollten Sie sedstattdessen verwenden. Hier ist es in einem Einzeiler:sed -i "1s@^@$(git branch | grep '^\*' | cut -b3-) @" $1
Ory Band
10

Fügen Sie den folgenden Code in die Datei prepare-commit-msg ein.

#!/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

Es wird ein Zweigname zur Festschreibungsnachricht hinzugefügt, mit Ausnahme von Merge-Commit. Das Merge-Commit enthält standardmäßig Zweiginformationen, sodass kein zusätzlicher Zweigname erforderlich ist und die Nachricht hässlich wird.

Tim
quelle
1
Dadurch wird die Festschreibungsnachricht nicht geändert, wenn das Wort "Zusammenführen" in der Nachricht gefunden wird.
Thoroc
1
@thoroc das ist technisch korrekt; Bei normalem Gebrauch ist dies jedoch keine große Sache. Die zu analysierende Festschreibungsnachricht ist die "Standardnachricht", bevor Sie sie bearbeiten. Solange Ihre Commit-Vorlage nicht das Wort "Zusammenführen" enthält, sollten Sie meiner Meinung nach in Ordnung sein (solange die anderen "Standard" -Nachrichten dies nicht tun, außer einer Standard-Commit-Nachricht zum Zusammenführen). Ich habe das ursprünglich falsch verstanden und glaube, ich habe es jetzt richtig.
Anfänger C
5

Inspiriert von Tims Antwort, die auf der obersten Antwort aufbaut, stellt sich heraus, dass der Hook "prepare-commit-msg" ein Argument dafür ist, welche Art von Festschreibung stattfindet . Wie in der Standard-Prepare-Commit-Nachricht zu sehen ist, handelt es sich bei $ 2 um 'Merge', dann um ein Merge-Commit. Daher kann der Fallschalter so geändert werden, dass er Tims Funktion addBranchName () enthält.

Ich habe meine eigene Präferenz für das Hinzufügen des Zweignamens und alle nicht kommentierten Teile des Standard- prepare-commit-msg.sampleHooks angegeben.

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
Anfänger C.
quelle
4

Wenn Sie es global machen möchten (für alle Projekte):

Erstellen Sie eine git-msgDatei mit dem Inhalt von shytikovs Antwort und legen Sie sie in einem Ordner ab:

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

Aktivieren Sie nun Hooks:

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

und git initwieder in jedem Projekt, das Sie verwenden möchten.

Maroun
quelle
2
Um diese Funktion nutzen zu können, musste ich 'commit-msg' in ein 'hooks'-Verzeichnis innerhalb des für' init.templatedir 'konfigurierten Verzeichnisses stellen, damit, wenn das gesamte Templatedir auf' git init 'kopiert wird,' commit- ' msg 'landet im Verzeichnis' .git / hooks 'des Projekts.
Dan
2

Ich hatte Probleme, diese Lösungen unter MacOS zum Laufen zu bringen, da BSD sedanstelle von GNU verwendet wird sed. Ich habe es geschafft, ein einfaches Skript zu erstellen, das die Arbeit erledigt. Immer noch mit .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 

Dies setzt einen ähnlichen Namensnamen für Zweige voraus functional-desc_JIRA-NUMBER. Wenn Ihr Filialname nur Ihre Jira-Ticketnummer ist, können Sie einfach alles von der Pipe bis zur f2 loswerden. Es erfordert auch, dass Sie eine Datei mit dem Namen .gitmessagein Ihrem Home-Verzeichnis haben.

PhPGuy
quelle
2

Wenn Sie möchten, dass das JIRA-Ticket zur Festschreibungsnachricht hinzugefügt wird, verwenden Sie das folgende Skript.

Nachricht so etwas wie festschreiben PROJECT-2313: Add awesome feature Dies erfordert, dass Ihr Filialname mit dem jira Ticket beginnt.

Dies ist eine Kombination dieser Lösungen:

Es wurde für OS X mit dem geändert sed -i '.bak' und funktioniert auch mit 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
quelle