GitHub Cloud Commitメッセージを制限しよう

Git
この記事は約7分で読めます。
記事内に広告が含まれています。

Gitを利用する際、コードの品質やプロジェクトの整合性を保つために、コミットメッセージのパターンを統一することが重要です。

# NG例(わかりにくい)
git commit -m "main.c modify"

# OK例(わかりやすい)
git commit -m "fix: functionA error code"

本記事では、Gitのコミットメッセージを正規表現で制限する方法に触れます。
→ つまり、指定した正規表現に当てはまらない場合は、拒否する。

具体的には次のケースに触れていきます。

制御場所概要
Gitクライアント定番ですね。
.git/hooks/commit-msgを利用します。
GitHub Cloudrulesetsを使います。

GitHub Cloudのrulesetsについて補足します。

具体的には「Restrict commit metadata」を指定します。

  • 2023年頃からサポートされています。
  • プランがEnterpriseじゃないと利用出来ないっぽいです。

※Server版は本記事では触れませんが、Server版であれば自由にServer処理でのHook配置が可能ですね。

今回試す条件

コミットメッセージの条件です。

  • コミットメッセージの先頭が「feat」「fix」「docs」「style」「refactor」「test」「chore」のいずれかで始まる。
  • その後に「:」と半角スペースが続く。
  • メッセージ本文が10文字以上50文字以下である。

これを満たす正規表現は次の通りです。

^(feat|fix|docs|style|refactor|test|chore): .{10,50}

例えば、

  • feat: Add user login feature → OK(featで始まり、本文が15文字)
  • fix: Bug fixes → NG(本文が9文字)
  • style: Formatting updates → OK(styleで始まり、本文が20文字)

では試していきましょう!

Gitクライアントフック

ローカルリポジトリ内の「.git/hooks/commit-msg」を次のように編集します。

#!/bin/sh
# .git/hooks/commit-msg

PATTERN="^(feat|fix|docs|style|refactor|test|chore): .{10,50}$"

if ! grep -qE "$PATTERN" "$1"; then
  echo "Error: Invalid commit message pattern."
  echo "Commit message must match the pattern: $PATTERN"
  exit 1
fi

linuxだと実行権限(x)を付与しないとダメなことがあります。
(chmod +x .git/hooks/commit-msg)

# NGケース
$ git commit -m "text modify"
Error: Invalid commit message pattern.
Commit message must match the pattern: ^(feat|fix|docs|style|refactor|test|chore): .{10,50}$

# OKケース
$ git commit -m "feat: 1234567890"
[master (root-commit) e5deff4] feat: 1234567890
 1 file changed, 4 insertions(+)
 create mode 100644 test.txt

上手くいきました。

さて、Gitクライアントフックはお手軽ですが、問題点があります。

Gitクライアントフックの問題点
  • 各クライアントで個別設定が必要です。
  • 利用者が多い場合に統一することは不可能でしょう。
    → Gitリポジトリに事前配置して、全員が同じように実行というのは出来ません(もし出来たら、攻撃の的ですからね・・・)

GitHub Cloud Rulesets

リポジトリの設定画面からRulesetsに行きましょう

◇ Settings ->Rules -> Rulesets

Restrict commit metadataを開いて次のように設定します。

  • Applies to:Commit message
  • Requirement:Must match a given regex pattern
  • Maching pattern:^(feat|fix|docs|style|refactor|test|chore): .{10,50}

設定後の画面です。

本当はここで動作確認が出来たらいいのですが・・・。まだ出来ないようです。

早速、GitHub上でコミット操作を試します。

→ 期待通りのエラーが発生しました。

続いてGitクライアントからのPush時に拒否されるか試してみます。

$ git commit -m "aaaa"
[main a1f08e9] aaaa
 1 file changed, 3 insertions(+), 1 deletion(-)

$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 254 bytes | 254.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote: Review all repository rules at http://github.com/xxxx/test/rules?ref=refs%2Fheads%2Fmain
remote:
remote: - Commit message must match a given regex pattern: ^(feat|fix|docs|style|refactor|test|chore): .{10,50}$
remote:   Found 1 violation:
remote:
remote:   2d8878579a2fcf2a9cd5500d81cca1bd9e75f18e
remote:
To https://github.com/xxxx/test.git
 ! [remote rejected] main -> main (push declined due to repository rule violations)
error: failed to push some refs to 'https://github.com/xxxx/test.git'

期待通りの結果です。

GitHub利用の場合、Push時にコミットメッセージの内容がチェックされます。

リモートリポジトリにとっては、精度の悪いコミットが防げれば良いので十分ですね。一方で、利用者にとってはコミットメッセージの修正が必要なため、少し面倒ですが。

コミットメッセージを修正して、再度Pushしてみます。

$ git commit --amend
[main 27507d2] feat: 123456789000
 Date: Fri Sep 6 17:02:24 2024 +0900
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 267 bytes | 267.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/xxxx/test.git
   17dd6d1..e7d6778  main -> main

今度は上手く行きました。

コメント

Top
タイトルとURLをコピーしました