はじめに
以前の記事でGoogle AI StudioでAWSアイコンクイズアプリを作った記事を投稿したのですが、環境をGitHubにコミットする際、躓いたので備忘録として残しておこうと思います。
アプリ構成
index.html
AWS_icon_pkg/ # サブフォルダ含め、総数854のアイコンファイル
┣━ Architecture-Group-Icons/ # アイコンファイル数:15
┣━ Architecture-Service-Icons/ # アイコンファイル数:300
┣━ Category-Icons/ # アイコンファイル数:26
┗━ Resource-Icons/ # アイコンファイル数:513
アプリ構成は極めてシンプルで、html以外は全て描画用のアイコンファイル(png)です。
AWSのアーキテクチャアイコンは公式のものを使用しています。
ファイル形式はpngとsvgの2形式、イメージファイルも複数ピクセルサイズがあり、ファイル総数が4,000以上にもなるので、形式はpng、イメージファイルのサイズは1種類に整理して、ファイル総数850程にしました。
開発環境・使用ツール
GitHub
VS code :CLIによるGit操作用
AmazonQ :Git操作エラー時の調査用
1.大量ファイルによるコミット失敗
$ git commit -m "many icon files commit."
C:\Users\(ユーザ名).git-secrets\git-secrets: line 116: /mingw64/libexec/git-core/git: Argument list too long
大量のアイコンファイルをコミットした際、見慣れないエラーが出ました。
コミットしただけなのに、「Argument list too long」(引数が多すぎる)となる理由が分かりません。
GREP_OPTIONS= LC_ALL=C git grep -nwHEI ${options} "${combined_patterns}" -- "${files[@]}"
エラーで示されたgit-sceretsの116行目を見てみたのですが、何かをgrepしている程度しか分かりません。
VS CodeでAmazonQに訊いてみると、この116行目の処理は git_grep() 関数内にあり、git grep コマンドを実行してコミット対象ファイルの中にシークレット情報(機密情報)が含まれていないか走査する処理を行っていると分かりました。
コミットエラーの真因
エラーとなったプロセスは以下の通りでした。
- コミット対象となる多数のファイルパス(今回の場合800件以上)が配列 ${files[@]} に格納されます。
- 116行目で、その全ファイルパスを git grep ... -- file1 file2 file3 ... のようにひとつのコマンドの引数として一度に渡そうとします。
- OS(Windows/MSYS2/MinGW)が受け入れられる引数の文字数上限を超えてしまい、エラーが発生してコミットが失敗します。
2.大量ファイルをコミットするための対処法
AmazonQが提案してきた対処法は以下の2つでした。
対処法1. 分割してコミットする(最もシンプル)
# 例:フォルダごとに分けてコミット
git add ./AWS_icon_pkg/Compute/
git commit -m "add Compute icons"
git add ./AWS_icon_pkg/Storage/
git commit -m "add Storage icons"
対処法2. git-secrets のフックを一時的に無効化する
# フックをリネームしてpre-commitを無効化する(pre-commitをコールしない)
mv .git/hooks/pre-commit .git/hooks/pre-commit.bak
# コミットを実施
git commit -m "many icon files commit."
# フックをリネーム前に戻してpre-commitを有効化する
mv .git/hooks/pre-commit.bak .git/hooks/pre-commit
今回の対処法
今回はシークレット情報が含まれないアイコンファイルしか扱っていないので、対処法2で解決しました。
対処法1を最初に試したのですが、1フォルダにファイル数が数百個あるため、同じ事象は避けられませんでした。
最後にフックのお浚い
今回、エラーになったのは、git commit 実行直前に行う Hookによる仕組みでしたが、Hook処理はgit自体の仕組みなので、全然知らないところで処理が実行されていることを知ることが出来ました。
最後に、他にどのようなHookの仕組みがあるのか一部を記して、当記事を締めたいと思います。
主要な Git Hooks 一覧
1. コミット関連(クライアント側)
ローカルでコードを変更・コミットする際に実行されるフックです。
| フック名 | 実行タイミング | 主な用途・使い道 |
|---|---|---|
| pre-commit | コミット実行直前(メッセージ入力前) | リント(静的解析)、フォーマットチェック、シークレット検出(git-secrets など) |
| prepare-commit-msg | コミットメッセージのデフォルト作成直後 | Issue番号の自動挿入、テンプレートの適用 |
| commit-msg | コミットメッセージ入力完了後 | メッセージフォーマット検証(Conventional Commits などの規則チェック) |
| post-commit | コミット完了直後 | 通知送信、ビルド結果の保存、ログ出力 |
2. プッシュ・ワークフロー関連(クライアント側)
ローカルからリモートへデータを送信・切り替える際に実行されるフックです。
| フック名 | 実行タイミング | 主な用途・使い道 |
|---|---|---|
| pre-push | git push 実行直前 | 自動テスト(Unit Test)の実行、ビルドチェック |
| post-checkout | git checkout や git switch 完了時 | 依存関係パッケージ(npm install など)の自動更新チェック |
| post-merge | git merge 完了時 | マイグレーション実行、設定ファイルの再ロード |
| pre-rebase | git rebase 実行直前 | リベースしてはいけないブランチ(main 等)の保護 |
3. サーバー側(リモートリポジトリ側)
GitHub / GitLab や自作の Git サーバー側で受信時に実行されるフックです。
| フック名 | 実行タイミング | 主な用途・使い道 |
|---|---|---|
| pre-receive | サーバーがプッシュを受け取った直後(更新前) | ブランチ保護規則、権限チェック、全般的なポリシー強制 |
| update | ブランチごとに更新が適用される直前 | 特定ブランチへの直接プッシュ禁止設定 |
| post-receive | サーバー側での更新完了直後 | CI/CDパイプラインの起動、Slack等への更新通知、デプロイ実行 |