Closed7

simple-git-hookでも、ブランチ名からIssue番号を抽出して、コミットメッセージに入れたい

よしよし

使用するフックの種類

最初は commit-msg でやろうとしたものの、コミットメッセージのうち、1行目の末尾に Issue 番号付けるのって、なんかめんどくさくない?と思った。
やるとしたら、引数のコミットメッセージファイルを1行ずつ読んでいって、1行目の末尾に Issue 番号付与 + 残りの行を結合とかなのかな。

この記事で、あらかじめコミットメッセージテンプレに特定の文字を入れておいて、prepare-commit-msg でそれを置換するというのをやっていて、こっちの方がやりやすそうと思った。

https://tech.mobilefactory.jp/entry/2021/12/06/000000

なので、今回はこっちにする。

よしよし

ベース

この記事を参考にして、ベースを作成。
https://zenn.dev/liam/articles/7df3aea7850b3b

引数の$1にコミットメッセージファイルの情報が入ってくるらしい。

引数が入らない?

試してみたら、一向に$1の中身が入らなかったので、$#で引数の数を見てみると0。
なんで引数入らんの?となっていたところ、simple-git-hooks の設定時に引数渡すようにしていないからだった。
\"$@\"で元々の引数をそのまま渡すようにした。

"simple-git-hooks": {
    "pre-commit": "yarn run -s lint-staged",
    "prepare-commit-msg": "./git-hook/commit-msg \"$@\""
  },
よしよし

ブランチ名に Issue 番号がないときは、このまま続行していいか確認するようにしたい

シェルで応答処理やりたいときは、read を使えばいいらしい。

https://dev.classmethod.jp/articles/waiting-for-your-input-with-read-command/

...が、なぜか一向に read のところで止まってくれなかった。

ググるとループ処理の中でやるとそういうことがあるらしいと、いくつかヒットした。
別にループの中ではやってないんやけどなと思いつつ、多分似たような状況で勝手に標準入力されてしまっていそう。

コンソールから入力したやつしか受け付けないようにするというのができるっぽかったので、それで対応したら止まってくれるようになった。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12125082002

よしよし

sed コマンドの仕様の違い

  • Windows の Git Bash など or Linux:GNU sed
  • Mac:POSIX sed

で、微妙に挙動が違うらしい。
今回、置換してファイル上書きに使用する-iオプションがその一つで、Mac の場合はバックアップ用のファイル拡張子を-iの後につける必要があるとのこと。
特にバックアップファイルを作りたくない場合は空文字でもいいんだってさ。

Git Bash の sed コマンド

> sed --version
sed (GNU sed) 4.8
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jay Fenlason, Tom Lord, Ken Pizzini,
Paolo Bonzini, Jim Meyering, and Assaf Gordon.

This sed program was built without SELinux support.

GNU sed home page: <https://www.gnu.org/software/sed/>.
General help using GNU software: <https://www.gnu.org/gethelp/>.
E-mail bug reports to: <bug-sed@gnu.org>.

Mac (version オプションがないらしく怒られる)

> sed --version
sed: illegal option -- -
usage: sed script [-Ealnru] [-i extension] [file ...]
	sed [-Ealnu] [-i extension] [-e script] ... [-f script_file] ... [file ...]
よしよし

最終形

とりあえず Windows の Git Bash で動くやつ

(#Issue)の部分を置換するイメージ。

.gitmessage
(#Issue)

# ==== Type ====
# --TIL活動--
# TIL Docs: TIL活動のドキュメント化
#
# --ポートフォリオサイト--
# feat: 機能追加
# fix: バグ・typo・エラー修正
# refactor: リファクタリング・改善
# update: ライブラリ・バージョン更新
# data update: ポートフォリオデータ更新
# test: テストの追加・改善
# settings: 環境周りの設定の追加・改善
# docs: ドキュメント追加・更新
# remove: 不要な機能削除
# misc: その他

# ==== Format ====
# type: Subject(#issue)
#
# Commit body...
#
# ※push時にデプロイをしない場合は [skip ci] をつける

# ==== The Seven Rules ====
# 1. Separate subject from body with a blank line(件名と内容は空白行で区切る)
# 2. Limit the subject line to 50 characters(件名は50文字まで)
# 3. Capitalize the subject line(件名は大文字で)
# 4. Do not end the subject line with a period(件名をピリオドで終わらせない)
# 5. Use the imperative mood in the subject line(件名に命令法を使用する)
# 6. Wrap the body at 72 characters(内容は72文字以内で折り返す)
# 7. Use the body to explain what and why vs. how
#  (内容で、何が変わったか、なぜそうしたのか、どうやったのかを説明する)
#
# How to Write a Git Commit Message https://chris.beams.io/posts/git-commit/
git-hooks/prepare-commit-msg
#!/bin/sh

COMMIT_MSG_FILE=$1
MESSAGE=$(cat "$COMMIT_MSG_FILE")

ISSUE_NUMBER=$(git rev-parse --abbrev-ref HEAD | grep -Eo "^(feature|bugfix|release)/[0-9]+" | grep -Eo "[0-9]+")
if [ -z "$ISSUE_NUMBER" ]; then
  read -p "Issue 番号がブランチ名にないので置換できませんが、続行しますか? (y/N): " YM < /dev/tty
  case "$YM" in
    [yY]*) sed -i "s/(#Issue)//" $COMMIT_MSG_FILE ;;
    *) echo "abort." ; exit 1 ;;
  esac
fi

sed -i "s/(#Issue)/(#$ISSUE_NUMBER)/" $COMMIT_MSG_FILE

ちなみに Mac だとファイル作成時の権限が違うようで、実行権限の付与が必要だった

# Windows
-rwxr-xr-x  1 h_yoshikawa44  197609 508 1119 23:19 prepare-commit-msg

# Mac
-rw-r--r--  1 h_yoshikawa  staff  613 11 20 13:48 prepare-commit-msg
# 実行権限付与
chmod a+x git-hooks/prepare-commit-msg
package.json
// 抜粋
"simple-git-hooks": {
  "pre-commit": "yarn run -s lint-staged",
  "prepare-commit-msg": "./git-hooks/prepare-commit-msg \"$@\""
},
よしよし

BSD sed との互換性を考慮したもの

#!/bin/sh

# sed コマンドが GNU か BSD か確認
GNU_SED=true
sed --version 1>/dev/null 2>/dev/null || GNU_SED=false
echo $GNU_SED

# コミットメッセージ入力前に、ブランチ名から Issue 番号を抽出して置換する
COMMIT_MSG_FILE=$1
MESSAGE=$(cat "$COMMIT_MSG_FILE")

ISSUE_NUMBER=$(git rev-parse --abbrev-ref HEAD | grep -Eo "^(feature|bugfix|release)/[0-9]+" | grep -Eo "[0-9]+")
if [ -n "$ISSUE_NUMBER" ]; then
  if [ "$GNU_SED" == "true" ]; then
    sed -i "s/(#Issue)/(#$ISSUE_NUMBER)/" $COMMIT_MSG_FILE
  else
    sed -i "" "s/(#Issue)/(#$ISSUE_NUMBER)/" $COMMIT_MSG_FILE
  fi
  exit 0
fi

read -p "Issue 番号がブランチ名にないので置換できませんが、続行しますか? (y/N): " YM < /dev/tty
case "$YM" in
  [yY]*)
    if [ "$GNU_SED" == "true" ]; then
      sed -i "s/(#Issue)//" $COMMIT_MSG_FILE
    else
      sed -i "" "s/(#Issue)//" $COMMIT_MSG_FILE
    fi;;
  *) echo "abort." ; exit 1 ;;
esac

出力を無効化する参考
https://qiita.com/harasakih/items/868a850fcdc99a2c37b0

このスクラップは2022/11/24にクローズされました