Як додати ім'я гілки Git до повідомлення фіксації?


103

Мені потрібна допомога зі сценарієм Bash, який автоматично додасть ім'я гілки git як хеш у повідомленнях фіксації.


4
Для всіх, хто приходить сюди, здається, найкраща відповідь знаходиться внизу сторінки
Бен Таліадорос

Побічна примітка: все git branch | grep ...для отримання поточної гілки - це неправильний спосіб зробити це. Розглянемо або git symbolic-ref -q HEAD(як показано у цій відповіді ), або git rev-parse --abbrev-ref HEAD. Команда символічного відмови вийде з ладу, якщо ви знаходитесь на відокремленій ГЛАВІ, тому якщо ви хочете виявити цей випадок, використовуйте його. В іншому випадку, можливо, найкращий метод rev-parse - abbrev-ref.
Торека

Відповіді:


53

Використовуйте prepare-commit-msgабо commit-msg githook .

У вашому PROJECT/.git/hooks/каталозі вже є приклади .

В якості заходів безпеки вам доведеться вручну ввімкнути таку гачок у кожному сховищі, яке ви хочете використовувати. Хоча ви можете скопіювати скрипт і скопіювати його на всіх клонах у .git/hooks/каталог.


Дякую великому ведучому; спасибі. Якщо ви можете допомогти мені далі, за сам сценарій, я буду вдячний :)
Томер Ліхташ

5
Мені не потрібно, у вас вже є приклад, який робить саме те, що ви хочете , як я вже сказав, в .git/hooks/prepare-commit-msg.sample. =) Все, що вам потрібно змінити (дотримуючись вказівок у коментарях) - це скопіювати та вставити будь-яке рішення з stackoverflow.com/questions/1593051/…, який ви хочете
ninjagecko

4
@ninjagecko, для мене .git/hooks/prepare-commit-msg.sampleмістить три приклади. Перший для коментування розділу конфліктів, додавання git diff --name-status -rдо нього результату та додавання рядків підписаних повідомлень ... Немає додавання назви гілки до повідомлення фіксації. Тож я був змушений написати власний гачок.
шитиков

1
Це you will have to manually enable such a hook on each repository you wish to use itозначає, що ви повинні дати FILE виконувати дозволи? Якщо так, чи можу я відредагувати відповідь, щоб включити цю (чи можете ви, будь ласка)?
Дан Розенстарк

2
Чому це відповідь? Це більше схоже на те, щоб дозволити мені гугл для вас. Відповідь від @shytikov слід обрати
TheRealFakeNews

177

Ось мій commit-msgсценарій як приклад:

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

Створює таке повідомлення про фіксацію:

[branch_name]: [original_message]

[branch_description]

Я використовую номер проблеми як branch_name, опис проблеми розміщується в команді branch_descriptionusing git branch --edit-description [branch_name].

Більше про описи галузей ви можете знайти в цьому запитанні .

Приклад коду зберігається в наступному Gist .


8
Цей скрипт стискає багаторядкові передачі повідомлень в один рядок. Я замінив вашу заяву echo на: echo -n "$ NAME" ':' | cat - "$ 1"> / tmp / out && mv / tmp / out "$ 1"
Алекс Спенс

4
Помістіть цей файл у папку PROJECT / .git / hooks /
катастрофа

2
Це добре працює. Але для Mac мені довелося також встановити дозвіл, щоб він працював: >>> sudo chmod 755 .git / hooks / commit-msg
Manoj Shrestha

1
@ManojShrestha так, це повинно бути виконуваним
Девід Манн

2
@AlexSpence простіше, ніж ти можеш використовувати echo $NAME: "$(cat $1)" > $1. Це працює, тому що причина втрати нових рядків полягає в тому, що відлуння трактує кожен рядок $(cat "$1")як новий аргумент і повторює кожен з пробілом між ними. Оточуючи $(cat "$1")подвійні лапки, ехо трактує вихід кішок як єдиний аргумент. Також я не вважаю за необхідне цитувати, $1оскільки його значення.git/COMMIT_EDITMSG
PiersyP

30

Трохи простіший сценарій, який додає ім'я гілки до повідомлення фіксації, перш ніж редагувати його. Тож якщо ви хочете змінити або видалити його, можете.

Створіть цей файл .git / hooks / priprema-фіксація-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
Я отримую: sed: 1: ".git/COMMIT_EDITMSG": invalid command code .при використанні цього.
Адам Паркін

1
Ага, різниця в Mac OSX, дивіться: hintsforums.macworld.com/showpost.php?p=393450&postcount=11 для виправлення
Адам Паркін

2
як перевірка справи про поправки та виправлення
погопауле

3
OSX: розширення файлу потребує роботи, якщо ви отримуєте вищезгадане повідомлення про помилку. sed -i '.bak' "1s/^/$branchName : \n/" $1
canintex

Ви можете використовувати @як sedроздільник замість того, що /передні косої риси мають більше шансів відображатися у назві гілки чи виконувати повідомлення, підкручуючи sed.
Ory Band

28

Ви можете зробити це за допомогою комбінації гачків підготовки-фіксації та попереднього фіксації.

.git / гачки / підготовка-фіксація-msg

#!/bin/sh

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

.git / гачки / попередньо здійснити

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

Встановити дозволи

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

Зауважте, що це може видалити оригінальне повідомлення про фіксацію, якщо ви використовуєте, --amendнаприклад. Замість використання echoви повинні використовувати sedзамість цього. Ось це в одному лайнері:sed -i "1s@^@$(git branch | grep '^\*' | cut -b3-) @" $1
Ory Band

10

додайте нижче наведений код у файл-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

Він додасть ім'я гілки для повідомлення повідомлення, за винятком об'єднання-фіксування. За замовчуванням злиття-фіксація містить інформацію про відділення, тому додаткова назва гілки не потрібна, і повідомлення стає некрасивим.


1
Отже, це не змінить повідомлення про фіксацію, коли воно знайде слово злиття в повідомленні?
торок

1
@thoroc, що технічно правильно; Однак у звичайному використанні це не велика справа. Повідомлення про фіксацію, яке розбирається, є "типовими" до редагування. Тож, поки у вашому шаблоні фіксації немає слова "злиття", я вважаю, що вам слід добре (до тих пір, поки інші повідомлення "за замовчуванням" не мають, за винятком повідомлення про фіксацію злиття за замовчуванням). Я спочатку неправильно зрозумів це, і вважаю, що зараз це правильно.
Новачок C

5

Натхненний відповіддю Тіма, який ґрунтується на верхній відповіді, виявляється, гак priprav-фіксації-msg береться за аргумент того, який тип комісії відбувається . Як видно з замовчування priprav-commit-msg, якщо $ 2 є "злиттям", то це об'єкт злиття. Таким чином, вимикач регістру може бути змінений, щоб він включав функцію Тіма addBranchName ().

Я включив власні переваги щодо того, як додати ім'я гілки та всі некомментовані частини prepare-commit-msg.sampleгака за замовчуванням .

підготовка-фіксація-мсг

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

Якщо ви хочете зробити його глобальним (для всіх проектів):

Створіть git-msgфайл із вмістом відповіді шитікова та помістіть його в якусь папку:

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

Тепер увімкніть гачки:

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

і git initзнову в кожному проекті, який ви хочете використовувати.


2
Я виявив, що для використання цієї функції мені довелося помістити 'commit-msg' у каталог 'гачки' всередині каталогу, налаштованого на 'init.templatedir', щоб, коли весь templatedir скопіювався на 'git init', 'commit- msg 'потрапляє в каталог' .git / hooks 'проекту.
Dan

2

У мене виникли проблеми з тим, як ці рішення працювати на MacOS через те, що він використовує BSD sedзамість GNU sed. Мені вдалося створити простий сценарій, який виконує цю роботу. Все ще використовується .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 

Це передбачає стандарт імені гілки, подібний до functional-desc_JIRA-NUMBER. Якщо назва вашого відділення - лише номер вашого квитка Джира, ви можете просто позбутися від усього, починаючи від "F2". Це також вимагає, щоб .gitmessageу вашому домашньому каталозі був файл, названий .


2

Якщо ви хочете, щоб квиток JIRA був доданий до повідомлення про фіксацію, скористайтеся нижче сценарієм.

Повідомлення про щось, наприклад, для PROJECT-2313: Add awesome feature цього потрібна назва вашої філії, щоб розпочати з jira Ticket.

Це поєднання цих рішень:

Він модифікований для OS X, sed -i '.bak'а також працює і з 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

Це добре працює у файлі на стороні клієнта: підготовка-фіксація-msg для автоматичного заповнення префіксу фіксації. Але якщо я хочу зробити те ж саме на гачку на стороні сервера, це сервер bitbucket (в моєму випадку), і я намагаюся додати цю логіку на попередньо отриманий гачок на шляху до сервера Bitbucket: BITBUCKET_HOME / shared / data / repositories / <repository-id> / hooks / 21_pre_receive, він не працює як "git symbolic-ref -q HEAD", даючи "master", хоча я здійснюю з моєї функції / abc гілки з боку клієнта. Чи є інший шлях сюди?
сантош
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.