simple-git-hookでも、ブランチ名からIssue番号を抽出して、コミットメッセージに入れたい
使用するフックの種類
最初は commit-msg でやろうとしたものの、コミットメッセージのうち、1行目の末尾に Issue 番号付けるのって、なんかめんどくさくない?と思った。
やるとしたら、引数のコミットメッセージファイルを1行ずつ読んでいって、1行目の末尾に Issue 番号付与 + 残りの行を結合とかなのかな。
この記事で、あらかじめコミットメッセージテンプレに特定の文字を入れておいて、prepare-commit-msg でそれを置換するというのをやっていて、こっちの方がやりやすそうと思った。
なので、今回はこっちにする。
ベース
この記事を参考にして、ベースを作成。
引数の$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 を使えばいいらしい。
...が、なぜか一向に read のところで止まってくれなかった。
ググるとループ処理の中でやるとそういうことがあるらしいと、いくつかヒットした。
別にループの中ではやってないんやけどなと思いつつ、多分似たような状況で勝手に標準入力されてしまっていそう。
コンソールから入力したやつしか受け付けないようにするというのができるっぽかったので、それで対応したら止まってくれるようになった。
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)
の部分を置換するイメージ。
(#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/
#!/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 11月 19 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
// 抜粋
"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
出力を無効化する参考
記事化したのでクローズ