create-commit
Conventional Commits 形式で git コミットを作成する。staged 差分から type/scope を推定し、breaking change やシークレット混入 (.env 等) を検出。pre-commit フックを必ず通す (`--no-verify` 不可)。「コミットして」「git commit」「変更を記録して」などで使用。
By fandhe-ai · 756 installs
npx skills add fandhe-ai/agent-cli-skills --skill create-commit
Source repository · Upstream listing
create commit
変更内容を分析して Conventional Commits 形式でコミットを作成します。
フロー
Step 1: 変更内容を確認する
staged がない場合は git diff も確認してユーザーに staging を案内する。
Step 2: シークレット混入チェック(必須)
コミット実行前に、staged 差分へ秘密情報が含まれていないことを確認する。
検査は (a) 機械照合 と (b) 目視レビュー の 2 段構えである。(a) だけでは不十分であり、
(b) は (a) が何も検出しなかった場合でも必ず実施する (理由は後述の「機械照合の限界」)。
(a) 機械照合
パターンは変数へ一度だけ定義し、自己テストと本検査で同じ文字列を使う。 grep の実装差
(BSD grep / GNU grep / ugrep)で BRE の \+ の解釈が割れ、正規表現が構文エラーになることがある。
エラーになった grep は非ゼロで終わるため、 ... echo "検出なし" の形だと 秘密情報があっても
「検出なし」と報告される (fail open)。これは検出側( grep E )だけでなく 除外側( grep vE )も
同じ で、除外パターンが壊れると一致済みの行が消えて「検出なし」になる。自己テストは除外側まで
含めて実行する。
定義と検査を別のコードブロックに分けてはならない。コードブロックはそれぞれ独立したシェルで
実行され得るため変数が引き継がれず、かつ「テストされていない正規表現」が生まれる余地を作る。
以下は 1 ブロックで完結させる。
1・2・4 のいずれかが検出された場合は コミットを中止 し、ユーザーに警告して該当ファイルの
unstage・該当行の除去を案内する。例示値・プレースホルダ等の誤検知と判断できる場合のみ、
ユーザーの明示確認を得てから続行する。
3 が検出された場合は中止せず、 該当行をユーザーへ提示して実値かどうかを確認 したうえで
判断する(実値ならコミットを中止する)。3 は誤検知率が構造的に高いため自動中止にはしない。
リネーム(4)が検出された場合は、シークレットの内容が新しいファイル名の下に残っていないかを
確認し、残っている場合は中止する。削除のみのコミット( .env の削除・漏洩キーの除去)は
検出対象外でありそのまま続行してよいが、 認証情報ファイルの削除(D)と別名ファイルの追加(A)が
同一コミットに含まれる場合 は、内容が別名で追加し直されていないか(実質的なリネームでないか)を
差分で確認してから続行する。
(b) 目視レビュー(機械照合が「検出なし」でも必須)
追加行を読み、次の観点で秘密情報が含まれていないかを判断する。
観点 例
任意名の認証情報 dbPass ・ clientKey ・ token2 等、上記の鍵名リストに無い変数名
構造化ファイル内の実値 config.yml / settings.json / .tf / k8s manifest に直接書かれたパスワード
高エントロピー文字列 用途不明の長いランダム文字列(base64・hex)
接続情報の断片 ホスト名・ポート・ユーザー名と値がセットで並んでいる箇所
バイナリ・エンコード済み base64 でエンコードされた認証情報(k8s Secret の data: 等)
秘密情報と判断した、または判断が付かない場合は コミットを中止 し、ユーザーへ該当箇所を提示して確認する。
機械照合の限界(この手順の契約)
(a) はパターン照合であり、 網羅的な検出ではない 。次のものは原理的に検出できない。
任意の変数名に代入された認証情報(鍵名リストに載っていないもの)
値の形式に規則性が無い認証情報(多くの自社発行トークン・DB パスワード)
3 の除外パターンに偶然一致してしまう実値
したがって Step 2 の契約は「(a) が検出しなければ安全」ではなく、
「(a) で明白なものを機械的に落とし、(b) で残りを人が判断する」 である。
組織側で GitHub の secret scanning / push protection を有効化している場合、それは
push 時点の 追加の 防御線であり、この手順の代替にはならない(ローカルコミット時点では働かない)。
Step 3: Conventional Commits type を決定する
type 用途
feat 新機能
fix バグ修正
docs ドキュメントのみの変更
refactor 機能変更なしのコードリファクタリング
test テストの追加・修正
chore ビルドプロセス・補助ツール等の変更
style コードスタイルのみの変更(空白、フォーマット等)
build ビルドシステムや外部依存関係の変更
ci CI 設定の変更
perf パフォーマンス改善
Step 4: scope を推定する
変更ファイルのパスから scope を推定する。
複数にまたがる場合は省略可。
Step 5: コミットメッセージを生成してユーザーに確認する
フォーマット: type(scope): subject
例:
ユーザーに提案して確認を取る。
Step 6: コミットを実行する
重要 : no verify は絶対に使用しない(pre commit フックを迂回しない)。
検証
コミット完了後、以下で確認する。
最新コミットのメッセージが type(scope): subject 形式になっているか確認する
git show stat HEAD で変更ファイルの一覧が意図通りかを確認する
よくある失敗
問題 回避策
複数の関心事を 1 コミットに混ぜる 関心事ごとに git add p で staging を分けて別コミットにする
type を誤選定する(バグ修正に feat 、機能追加に fix ) Step 3 の type 表を参照し、差分の意図を優先して選ぶ
シークレットチェックを飛ばして type 決定に進む Step 2 は省略不可。検出時はコミットを中止してユーザーに警告する
no verify でフックを回避しようとする フック失敗の原因を調査・修正してから再コミットする(回避は禁止)
件名が 72 文字を超える scope を省略するか subject を短縮する。詳細は body に書く
注意事項
Breaking change がある場合は ! を付ける: feat!: ... または body に BREAKING CHANGE: を記述
件名は命令形・現在形で記述(日本語可)
件名は 72 文字以内
.env や認証情報ファイルが含まれる場合は警告してコミットを中止する(Step 2 で必ず検出する)