🦔

GitHooksを利用したコミットメッセージ確認

に公開

GitHooksとは

Git の操作(コミットやプッシュなど)の前後に自動的に実行されるスクリプトのことです。開発のルールや自動化処理をローカルで仕込むことができる、Gitのカスタマイズ機能の一つです。pre-commit フック(コミットメッセージが入力される前に実行)、prepare-commit-msg フック(コミットメッセージエディターが起動する直前、デフォルトメッセージが生成された直後に実行)上記のような複数のフックが存在する。

commit-msg フック

commit-msg フックは、開発者の書いたコミットメッセージを保存した一時ファイルへのパスをパラメータに取ります。 このスクリプトがゼロ以外の値を返した場合、Git はコミットプロセスを中断します。これを使えば、コミットを許可して処理を進める前に、プロジェクトの状態やコミットメッセージを検査できます。

Git - Git フック

このフックは、提案されたコミットログメッセージを保持するファイルの名前を1つのパラメータとして受け取ります。0以外のステータスで終了すると、コマンドは中止されます。このフックはメッセージファイルをその場で編集することができ、メッセージをプロジェクトの標準フォーマットに正規化するために使用できます。また、メッセージファイルを検査した後にコミットを拒否するためにも使用できます。

Git - githooks Documentation

commit-msg フックを利用して、スクリプトを実行する

実現したいこと

  • コミットメッセージに指定したprefixが存在しなければ、エラーになる
  • コミットメッセージの冒頭にissue番号を自動で追加する

実現した際のメリット

  • prefixの付け忘れを防止できる
  • コミットメッセージに「#123」のように issue 番号を記載すると、GitHubでは自動的にその番号にリンクが付与されるため、コミットの追跡性・可読性・チーム連携を高めることができる

スクリプトを作成する

# スクリプトファイルを作成する
touch .git/hooks/commit-msg
# スクリプトファイルの実行権限を追加する
chmod a+x .git/hooks/commit-msg
  • .git/hooks/commit-msgにスクリプトを作成することで、commit-msg フックになります。

スクリプトを編集する

vi .git/hooks/commit-msg

.git/hooks/commit-msg

#!/bin/bash
# Git Hooks: commit-msg スクリプト(コミットメッセージ検証 + ブランチ名から issue 番号自動追加)

# 処理開始
echo "Running Git Hooks: commit-msg"

# コミットメッセージ取得
readonly MSG="$(cat "$1")"

# 現在のブランチ名から issue 番号を取得(例: 123-some-feature → 123)
readonly ISSUE_NO="$(git branch --show-current |  sed 's/-.*//')"

# 使用可能な Prefix 一覧
readonly PREFIXES=(
  "feat:"
  "fix:"
  "docs:"
  "style:"
  "refactor:"
  "pref:"
  "test:"
  "chore:"
  "add:"
  "remove:"
)

# 初期状態はエラー(0: OK, 1: NG)
code=1

# Prefix チェック
for prefix in "${PREFIXES[@]}"; do
  if [[ "$MSG" == "$prefix"* ]]; then
    echo "Prefix OK: $prefix"
    #issue番号をコミットメッセージに追記
    sed -i "1s/^/#${ISSUE_NO} /" "$1"
    #終了コードを変更
    code=0
    break
  fi
done

# 結果出力
if [ "$code" -eq 0 ]; then
  echo "✨PASS!!"
else
  echo "================================================================"
  echo "コミットメッセージに Prefix が含まれていません。"
  echo ""
  echo "【書式】"
  echo "prefix: メッセージ内容"
  echo ""
  echo "【例】"
  echo "feat: 一覧ページ作成"
  echo ""
  echo "【使用可能な Prefix】"
  for prefix in "${PREFIXES[@]}"; do
    echo "- $prefix"
  done
  echo "================================================================"
  echo "commit-msg: FAIL"
fi

exit "$code"

解説

前提条件

  • ブランチ名の冒頭をIssue番号にする

GItHubのissue画面から、ブランチを作成しようとすると「issue番号-issueタイトル」になるように、ブランチ名を提案してくれるので、あまり忘れる心配もないと考えています。

(GitHub Issue画面でCreate a branchのリンクを押下した画面)

また、GitHubのIssue画面からブランチを作成し、そのブランチでPull Requestを作成 → マージした場合、Issueは自動でクローズされます。

Issueの作業のためのブランチの作成 - GitHub Docs

スクリプト解説

# コミットメッセージ取得
readonly MSG="$(cat "$1")"
  • $1には、コミットした際のコミットメッセージが格納されています。
# 現在のブランチ名から issue 番号を取得(例: 123-some-feature → 123)
readonly ISSUE_NO="$(git branch --show-current |  sed 's/-.*//')"
  • git branch --show-currentで現在のブランチ名を取得して、sedで冒頭のissue番号を抽出しています。
# 使用可能な Prefix 一覧
readonly PREFIXES=(
  "feat:"
  "fix:"
  "docs:"
  "style:"
  "refactor:"
  "pref:"
  "test:"
  "chore:"
  "add:"
  "remove:"
)
  • コミットメッセージ冒頭につけるprefixは下記のように使い分けています。
prefix 説明
feat: 新機能の追加。プロダクトの機能が増える変更。
add: 新しいファイルや依存関係、設定の追加。
remove: 不要なコードやファイルの削除。
fix: バグ修正。動作の不具合を修正する変更。
docs: ドキュメントの変更。READMEやコメントの修正・追加。
style: コードのフォーマットや見た目の変更(機能には影響しない)。
refactor: リファクタリング。動作は変えずにコードを整理・最適化。
perf: パフォーマンス改善。速度や効率を向上させる変更。
test: テストの追加・修正。
chore: ビルドプロセスやツールの設定など、雑務的な変更(プロダクトのコードやテストには影響しない)。
# 初期状態はエラー(0: OK, 1: NG)
code=1
  • 0以外のステータスで終了すると、コマンドは中止されます。
# Prefix チェック
for prefix in "${PREFIXES[@]}"; do
  if [[ "$MSG" == "$prefix"* ]]; then
    echo "Prefix OK: $prefix"
    #issue番号をコミットメッセージに追記
    sed -i "1s/^/#${ISSUE_NO} /" "$1"
    #終了コードを変更
    code=0
    break
  fi
done
  • for prefix in "${PREFIXES[@]}"; do 配列PREFIXESの各要素をprefixに代入しながらループ処理を行います。
  • if [[ "$MSG" == "$prefix"* ]];変数MSGの先頭が、現在のprefixで始まっているかを判定しています(プレフィックスの一致確認)。
  • sed -i "1s/^/#${ISSUE_NO} /" "$1"引数で渡されたファイル$1の1行目の先頭に#ISSUE_NOを追記します。
# 結果出力
if [ "$code" -eq 0 ]; then
  echo "commit-msg: PASS"
else
  echo "================================================================"
  echo "コミットメッセージに Prefix が含まれていません。"
  echo ""
  echo "【書式】"
  echo "prefix: メッセージ内容"
  echo ""
  echo "【例】"
  echo "feat: 一覧ページ作成"
  echo ""
  echo "【使用可能な Prefix】"
  for prefix in "${PREFIXES[@]}"; do
    echo "- $prefix"
  done
  echo "================================================================"
  echo "commit-msg: FAIL"
fi
  • ステータスによって結果の出力を変更します。

参考

GitのコミットメッセージにPrefixをつけよう! - Qiita

【Git Hooks】コミット時にコミットメッセージの自動チェックを行う。【commit-msg】 - Qiita

【永久保存版】シェルスクリプト完全攻略ガイド - Qiita

まとめ

Git Hooks を利用して、コミットメッセージにプレフィックスと issue 番号の記載を忘れないようにしました。この仕組みを導入してからは、書き忘れがなくなり、とても満足しています。もし誤りや改善点などがあれば、ご指摘いただけますと幸いです。

Discussion