Bagaimana cara menambahkan nama cabang Git ke pesan komit?

103

Saya butuh bantuan dengan skrip Bash yang secara otomatis akan menambahkan nama cabang git sebagai hash dalam pesan komit.

Tomer Lichtash
sumber
4
Bagi siapa pun yang datang ke sini tampaknya jawaban terbaik ada di bagian bawah halaman
Ben Taliadoros
Catatan samping: semua git branch | grep ...untuk mendapatkan cabang saat ini adalah cara yang salah untuk melakukan ini. Pertimbangkan baik git symbolic-ref -q HEAD(seperti yang ditunjukkan dalam jawaban ini ) atau git rev-parse --abbrev-ref HEAD. Perintah symbolic-ref akan gagal jika Anda berada di HEAD yang terpisah, jadi jika Anda ingin mendeteksi kasus itu, gunakanlah. Jika tidak, metode rev-parse --abbrev-ref mungkin yang terbaik.
torek

Jawaban:

53

Gunakan prepare-commit-msgatau commit-msg githook .

Ada beberapa contoh di PROJECT/.git/hooks/direktori Anda .

Sebagai tindakan keamanan, Anda harus mengaktifkan pengait semacam itu secara manual pada setiap repositori yang ingin Anda gunakan. Padahal, Anda dapat memasukkan skrip dan menyalinnya pada semua klon ke dalam .git/hooks/direktori.

ninjagecko
sumber
Terima kasih atas petunjuk yang bagus; Terima kasih. Jika Anda dapat membantu saya lebih jauh, dengan skrip itu sendiri, saya akan berterima kasih :)
Tomer Lichtash
5
Saya tidak perlu, Anda sudah memiliki contoh yang melakukan apa yang Anda inginkan , seperti yang sudah saya katakan, di .git/hooks/prepare-commit-msg.sample. =) Yang perlu Anda ubah (setelah mengikuti petunjuk di komentar) adalah menyalin-tempel solusi apa pun dari stackoverflow.com/questions/1593051/… yang Anda inginkan
ninjagecko
4
@ninjagecko, bagi saya .git/hooks/prepare-commit-msg.sampleberisi tiga contoh. Satu untuk mengomentari bagian konflik, menambahkan git diff --name-status -routput ke dalamnya dan menambahkan garis Signed-off-by ... Tidak menambahkan nama cabang ke pesan komit. Jadi saya terpaksa menulis pengait saya sendiri.
shytikov
1
Apakah ini you will have to manually enable such a hook on each repository you wish to use itberarti Anda harus memberikan izin eksekusi FILE? Jika demikian, bolehkah saya mengedit jawaban untuk memasukkannya (atau bisakah Anda, tolong)?
Dan Rosenstark
2
Kenapa ini jawabannya? Ini lebih seperti izinkan saya mencari di Google untuk Anda. Jawaban oleh @shytikov harus dipilih
TheRealFakeNews
177

Berikut commit-msgskrip saya sebagai contoh:

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

Membuat pesan komit berikut:

[branch_name]: [original_message]

[branch_description]

Saya menggunakan nomor masalah karena branch_name, deskripsi masalah ditempatkan ke perintah branch_descriptionusing git branch --edit-description [branch_name].

Lebih lanjut tentang deskripsi cabang dapat Anda temukan di T&J ini .

Contoh kode disimpan dalam Gist berikut .

shytikov.dll
sumber
8
Skrip ini memadatkan pesan komit multi baris ke satu baris. Saya mengganti pernyataan echo Anda dengan: echo -n "$ NAME" ':' | cat - "$ 1"> / tmp / out && mv / tmp / out "$ 1"
Alex Spence
4
Letakkan file ini ke dalam folder PROJECT / .git / hooks /
catanore
2
Ini bekerja dengan baik. Tetapi untuk Mac, saya juga harus menyetel izin untuk membuatnya berfungsi: >>> sudo chmod 755 .git / hooks / commit-msg
Manoj Shrestha
1
@ManojShrestha ya itu harus dapat dieksekusi
David Mann
2
@AlexSpence lebih sederhana, Anda dapat menggunakan echo $NAME: "$(cat $1)" > $1. Ini berfungsi karena alasan hilangnya baris baru adalah karena gema memperlakukan setiap baris $(cat "$1")sebagai argumen baru dan menggema masing-masing dengan spasi di antaranya. Dengan mengapit $(cat "$1")tanda kutip ganda, echo memperlakukan keluaran cat sebagai satu argumen. Juga saya rasa tidak perlu mengutip $1karena nilainya adalah.git/COMMIT_EDITMSG
PiersyP
30

Skrip yang lebih sederhana yang menambahkan nama cabang ke pesan komit sebelum Anda mengeditnya. Jadi jika Anda ingin mengubah atau menghapusnya Anda bisa.

Buat file ini .git / hooks / prepared-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
sumber
4
Saya mendapatkan: sed: 1: ".git/COMMIT_EDITMSG": invalid command code .saat menggunakan ini.
Adam Parkin
1
Aha, perbedaan Mac OSX, lihat: hintsforums.macworld.com/showpost.php?p=393450&postcount=11 untuk perbaikan
Adam Parkin
2
seperti pemeriksaan kasus amandemen dan
perbaikan
3
OSX: Membutuhkan ekstensi file agar berfungsi jika Anda mendapatkan pesan kesalahan di atas. sed -i '.bak' "1s/^/$branchName : \n/" $1
canintex
Anda dapat menggunakan @sebagai sedpemisah daripada sebagai /garis miring ke depan lebih mungkin untuk muncul di nama cabang atau pesan komit, mengacaukan sed.
Ory Band
28

Anda dapat melakukannya dengan kombinasi hook persiapan-commit-msg dan pra-commit.

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

Setel izin

sudo chmod 755 .git/hooks/prepare-commit-msg
sudo chmod 755 .git/hooks/pre-commit
Farid Movsumov
sumber
Perhatikan bahwa ini bisa menghapus pesan komit asli jika Anda menggunakan --amendmisalnya. Alih-alih menggunakan echoAnda harus menggunakan sedsebagai gantinya. Ini dia dalam satu kalimat:sed -i "1s@^@$(git branch | grep '^\*' | cut -b3-) @" $1
Ory Band
10

tambahkan kode di bawah ini di file prepared-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

Ini akan menambahkan nama cabang untuk melakukan pesan kecuali merge-commit. Merge-commit memiliki informasi cabang secara default sehingga nama cabang tambahan tidak diperlukan dan membuat pesan menjadi jelek.

Tim
sumber
1
Jadi ini tidak akan mengubah pesan komit ketika menemukan kata gabungan pada pesan?
thoroc
1
@thoroc yang secara teknis benar; Namun, dalam penggunaan normal ini bukanlah masalah besar. Pesan komit yang diurai adalah "yang default" sebelum Anda mengeditnya. Jadi selama template komit Anda tidak memiliki kata "merge" di dalamnya, saya yakin Anda akan baik-baik saja (selama pesan "default" lainnya tidak kecuali untuk pesan komit gabungan default). Awalnya saya salah paham tentang ini, dan yakin saya sudah benar sekarang.
Novice C
5

Terinspirasi oleh jawaban Tim yang dibangun di atas jawaban teratas, ternyata hook siap-commit-msg mengambil argumen seperti apa yang terjadi . Seperti yang terlihat di preparasi-commit-msg default jika $ 2 adalah 'merge' maka itu adalah komit gabungan. Jadi case switch dapat diubah untuk menyertakan fungsi addBranchName () Tim.

Saya telah menyertakan preferensi saya sendiri untuk bagaimana menambahkan nama cabang, dan semua bagian yang tidak diberi komentar dari prepare-commit-msg.samplehook default .

persiapkan-komit-pesan

#!/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
Pemula C
sumber
4

Jika Anda ingin menjadikannya global (untuk semua proyek):

Buat git-msgfile dengan isi jawaban shytikov , dan taruh di beberapa folder:

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

Sekarang aktifkan kait:

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

dan git initsekali lagi di setiap proyek Anda ingin menggunakannya.

Maroun
sumber
2
Saya menemukan bahwa untuk menggunakan fitur ini, saya harus meletakkan 'commit-msg' ke dalam direktori 'hooks' di dalam direktori yang dikonfigurasi untuk 'init.templatedir' sehingga ketika seluruh templatedir disalin di 'git init', 'commit- msg 'berakhir di direktori' .git / hooks 'proyek.
Dan
2

Saya mengalami masalah dalam mendapatkan solusi ini untuk bekerja di MacOS karena ia menggunakan BSD dan sedbukan GNU sed. Saya berhasil membuat skrip sederhana yang melakukan pekerjaan itu. Masih menggunakan .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 

Ini mengasumsikan standar penamaan cabang yang mirip dengan functional-desc_JIRA-NUMBER. Jika nama cabang Anda hanya nomor tiket Jira Anda, Anda dapat dengan mudah menyingkirkan semuanya mulai dari pipa hingga f2. Ini juga mengharuskan Anda memiliki file bernama .gitmessagedi direktori home Anda.

PhPGuy
sumber
2

Jika Anda ingin tiket JIRA ditambahkan ke pesan komit, gunakan skrip di bawah ini.

Lakukan pesan seperti PROJECT-2313: Add awesome feature ini. Ini memerlukan nama cabang Anda diawali dengan Jira Ticket.

Ini adalah kombinasi dari solusi ini:

Itu dimodifikasi untuk OS X, dengan sed -i '.bak'dan bekerja juga dari 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
sumber
Ini berfungsi dengan baik pada file sisi klien: persiapkan-komit-pesan untuk mengisi otomatis prefiks komit. Tetapi jika saya ingin melakukan hal yang sama pada hook sisi server, yang merupakan server bitbucket (dalam kasus saya) dan saya mencoba menambahkan logika ini pada hook pra-terima di jalur server Bitbucket: BITBUCKET_HOME / shared / data / repositories / <repository-id> / hooks / 21_pre_receive, ini tidak berfungsi karena "git symbolic-ref -q HEAD" memberikan 'master' meskipun saya melakukan dari fitur / cabang abc saya dari sisi klien. Apakah ada cara lain di sini?
santhosh