Claude Codeのコミット記録を確認・制御する方法
Claude CodeはコミットにCo-authored-byトレーラーを追加し、cloudやRemote Controlのセッションではclaude.aiリンクも記録します。push前に内容を確認し、公開情報として残る記録を制御する方法を解説します。
コミットに Claude Code が記録する内容
Claude Code は、作成するコミットメッセージの末尾に Co-authored-by: トレーラーを追加し、作成するプルリクエストの説明に帰属表示の行を追加します。クラウドまたは Remote Control で実行するセッションでは、claude.ai 上のセッションへのリンクも追加されます。これらはすべて、git の履歴内に保存されるプレーンテキストです。公開リポジトリへ push すると公開情報になり、誰かが履歴を書き換えるまで残ります。
正確な文言はリリース間で変更されているため、このガイドを含め、ガイドに記載されたトレーラーの内容をそのまま信用しないでください。自分のコミットを確認してください。以下の git コマンドは、このテーマで長期的に使える部分です。git のトレーラー処理は何年も同じ動作をしており、次のリリースで文言が変わっても、その動作は変わりません。
Git の trailer とは何か
trailer は、コミットメッセージの最後のブロックにある、Token: value のような形式の行です。Git に固定された token の一覧はありません。Signed-off-by:、Reviewed-by:、Fixes:、Co-authored-by: は、1 つの仕組みに基づく慣例です。リポジトリをホストする GitHub や GitLab などの forge は、これらを読み取り、コミットページに表示する内容を決めます。
Git は、このブロックの位置を厳密に解釈します。git interpret-trailers のドキュメントでは、このグループは 1 行以上の空行の後に置き、メッセージの末尾、または --- で始まる行の直前に置く必要があると説明されています。また、グループ全体が trailer であるか、「Git が生成した trailer またはユーザー設定の trailer を少なくとも 1 つ含み、かつ全体の 25% 以上が trailer で構成されている」必要があります。
ここでは、最後の規則が重要です。最後のブロックに URL だけの行や説明文の行がある場合、それは trailer ではありません。trailer ではない行が十分に含まれると、ブロック全体が trailer として解析されなくなります。そのため、コミットに Co-authored-by: 行が含まれているように見えても、trailer を正しく読み取るすべてのツールでは何も検出されないことがあります。
履歴にすでにあるトレーラーを読むにはどうすればよいですか?
まず、最新のコミットの生メッセージを表示します。
git log -1 --format=%B%B は、折り返しや再整形を行わず、保存されている件名と本文をそのまま表示します。この出力が正しい基準です。forge が表示する内容は、そのメッセージをレンダリングしたものにすぎません。
次に、git がどの行をトレーラーとして数えているかを確認します。
git log -1 --format=%B | git interpret-trailers --parse--parse は --only-trailers --only-input --unfold の短縮形です。そのため、出力されるのはトレーラーブロックだけです。正常な結果では、各トレーラーが1行ずつ表示されます。Co-authored-by: の行が明らかに見えるのに出力が空の場合は、上記の配置規則を満たしていません。
履歴全体を調べるには、キーを指定してトレーラーを取得します。
git log --format='%h %(trailers:key=Co-authored-by,valueonly)'古い git バージョンでは、%(trailers) に key= オプションを使用できません。メッセージ本文を検索する方法なら、どのバージョンでも使えます。
git log -i --grep='^Co-authored-by:' --format='%h %an %s'--grep はコミットメッセージに一致し、-i は大文字と小文字を区別しない検索にします。このトレーラーの大文字・小文字の表記はツールによって一貫していないため、重要です。push の前には、まだ送信していないコミットだけに対象を絞ります。
git log origin/main..HEAD --format=%Bこれらのコミットはまだローカルにあります。そのため、今なら低コストで変更できます。
GitHub では Co-authored-by: によって帰属表示がどのように変わりますか?
GitHub はこの trailer を読み取り、コミットページに 2 人目の作成者を表示します。その作成者のメールアドレスがアカウントに属している場合に限り、プロフィールにリンクします。GitHub の公式ドキュメントでは、コミットがコントリビューション グラフに表示される条件を「GitHub のアカウントに接続されたメールアドレスで作成されていること」と説明しています。そのため、どのアカウントにも属さないアドレスをプロフィールに関連付けることはできません。人間同士のペアであれば、これが目的のすべてです。共同作業者のアドレスがその人のアカウントに登録されているため、コミットは 2 人分として集計されます。どのアカウントにも所有されていないアドレスの場合、trailer はコミットページの表示だけを変更し、リポジトリのコントリビューター一覧は変更しません。
Git 自体はこの trailer を完全に無視します。git shortlog -sn と git log --author は、名前とメールアドレスを保持する author ヘッダーを読み取るため、ローカルの集計に co-author が表示されることはありません。ここでの帰属表示は、プレーンテキストの規約に forge の機能を重ねたものです。つまり、git 自体とホスト先の forge の違いがこの仕組みを分けています。
セッションリンクは別の問題です
トレーラーには共同作成者を記載します。セッション URL はトランスクリプトへの参照です。Claude Code の設定リファレンスでは、attribution.sessionUrl を「cloud および Remote Control のコミットから claude.ai セッションリンクを除外する」ためのキーとして説明しています。これにより、リンクの出所も分かります。Web 上のセッションと、Remote Control 経由で操作したセッションです。
このリンクは認証情報ではありません。そのセッションを開けるかどうかは、URL が知られているかではなく、アカウントのアクセス権で決まります。公開リポジトリから除外する理由は、もっと単純です。リンクは内部セッション ID を示す恒久的な公開テキストであり、一般の読者向けに作成されたものではない作業用トランスクリプトを指します。非公開リポジトリでは、逆の判断が成り立ちます。レビュー担当者がリンクを開き、変更に至った経緯を確認できるためです。これらのトランスクリプトの保存場所と保持期間については、Claude Code がセッションを保存し、再開する方法で説明します。
Claude Code のコミット帰属を制御する設定
2026 年 9 月 1 日時点の Claude Code 設定リファレンスに基づいて確認しています。これらのキーは、「Git and attribution」という見出しの下で文書化されています。
attribution: 「Claude Code がコミットと pull request に追加する帰属情報をカスタマイズする」attribution.commit: 「Claude Code がコミットに追加する trailer を変更または非表示にする」attribution.pr: 「pull request の説明に追加される帰属行を変更または非表示にする」attribution.sessionUrl: 「cloud および Remote Control のコミットから claude.ai のセッションリンクを省略する」includeGitInstructions: 「組み込みのコミットおよび PR 命令を system prompt から削除する」includeCoAuthoredBy: 非推奨と記載されており、「コミットと PR の帰属情報を非表示または変更するにはattributionを使用する」と説明されています
各キーで受け付けられる値は、ガイドではなく、設定リファレンスの該当する項目で確認してください。キー名は安定しています。変更されるのは、受け付けられる値とデフォルト値です。設定ファイルでキー名が正しくても、値の表記が間違っていると、エラーが表示されないまま失敗します。
どこに記述するかで、適用対象が決まります。~/.claude/settings.json は、開いたすべてのプロジェクトに適用されます。リポジトリのトップにコミットした .claude/settings.json は、そのリポジトリを clone した全員に適用されます。.claude/settings.local.json は、その 1 つのプロジェクトだけで使用する設定です。Claude Code はこのファイルを初めて書き込むときに、グローバル git excludes に追加するため、コミット対象から除外されます。優先順位は、managed settings、command line、project local、shared project、user の順です。したがって、チームメイトのローカルファイルは、あなたがコミットしたファイルより優先されます。コミットした設定は保証ではなく、デフォルトとして扱ってください。
次に、設定を確認します。設定したつもりであることは、証拠になりません。Claude Code に通常どおり次のコミットを作成させ、その結果を読み返してください。
git log -1 --format=%B
git log -1 --format=%B | git interpret-trailers --parsetrailer が引き続き出力される場合、変更内容がセッションに反映されていません。キーが壊れていると判断する前に、編集したファイルと、上記の優先順位を確認してください。
設定に依存しない制御
設定は 1 つのツールを構成します。リポジトリのルールは、別のツールを使うコントリビューターや、エージェントをまったく使わないコントリビューターにも適用できなければなりません。Git には、そのルールを置く場所があります。commit-msg hook は、メッセージファイルのパスを第 1 引数として実行されます。この hook でファイルを編集することも、コミット自体を拒否することもできます。
#!/bin/sh
# .githooks/commit-msg
grep -qi '^co-authored-by: claude' "$1" || exit 0
grep -vi '^co-authored-by: claude' "$1" > "$1.new" && mv "$1.new" "$1"chmod +x .githooks/commit-msg
git config core.hooksPath .githooks最初の grep は、処理対象がない場合に早期終了するため、通常のコミットへの負荷はほとんどありません。2 つ目は、一致する行を除いたメッセージを書き戻します。すべての trailer ではなく、1 つの正確なトークンだけを照合してください。「最後のブロックを削除する」フィルターでは、プロジェクトが必須とする Signed-off-by: 行まで削除してしまうためです。
.git/hooks はリポジトリの一部ではないため、そこに配置した hook は他の人に渡りません。core.hooksPath を使うと、コミット可能なディレクトリを git に指定できます。ただし、各ユーザーが自分で git config 行を実行する必要があります。Git はこの設定を自動では行いません。これは意図的な仕様です。clone 時にリポジトリ自身が実行ファイルをインストールできると、手元のマシンでコードを実行する手段になってしまうためです。
メッセージを書き換えるのではなくコミットを拒否するには、標準エラー出力にメッセージを表示し、hook から exit 1 してください。共有リポジトリでは、拒否する方が適切です。誰かのコミットメッセージを黙って編集すると、ルールを教えるのではなく隠してしまうためです。これは、git が関与する前、ツール呼び出しの段階で実行されるエージェント独自の hook とは別の層です。Claude Code の hook でツールを照合してブロックする方法では、その側を説明しています。
どちらの方法も、管理していないマシン上の hook に依存するため、fork からの pull request には対応できません。CI(継続的インテグレーション)でのチェックだけが、マージ前にすべてのコミットを確認できる層です。
if git log --format=%B "origin/${BASE_BRANCH:-main}..HEAD" | grep -qi '^co-authored-by: claude'; then
echo "Attribution trailer found. Rewrite the branch before merging." >&2
exit 1
fiルールは適用するだけでなく、文書化してください。人が読みやすい CONTRIBUTING.md の隣に置く AGENTS.mdがあれば、エージェントとユーザーに同じ内容を伝えられます。CI のチェックによって、そのルールが実際に守られます。
プッシュ前に末尾のトレーラーを削除する
直前に作成したコミットでは、次のようにします。
git log -1 --format=%B | grep -vi '^co-authored-by: claude' | git commit --amend -F --F -は標準入力から新しいメッセージを読み込みます。この方法で指定したメッセージでは、Git が先頭と末尾の空行を削除します。そのため、削除したトレーラーの後に残った空行も自動的に消えます。次に進む前に、git log -1 --format=%Bで結果を読み直してください。
ブランチ上の複数のコミットを変更する場合は、マージ先のブランチを対象に対話的な rebase を実行し、変更する各メッセージを reword として指定します。
git rebase -i origin/main最初に編集したコミット以降のすべてのコミットには、新しい hash が割り当てられます。コミットの hash には、メッセージと親コミットが含まれるためです。コミットがローカルにある間は問題ありませんが、ローカルにないコミットを変更すると影響が大きくなります。
push 後に trailer を削除する
自分だけが使用するブランチで、上記の手順で履歴を書き換えてから、そのブランチに上書き push します。
git push --force-with-lease--force-with-lease は、最後に fetch してからリモートが更新されている場合、push を拒否します。そのため、他の人が追加したコミットを黙って破棄することはありません。通常の --force には、このチェックがありません。
長い履歴全体にまたがる trailer を処理する場合、git filter-repo はすべてのメッセージを 1 回の処理で書き換えます。既存の working copy 内から clone を実行してください。URL には、すでに設定されている remote の URL が使用されます。
pip install git-filter-repo
git clone "$(git remote get-url origin)" ../project-rewrite
cd ../project-rewrite
git filter-repo --message-callback '
return b"\n".join(l for l in message.split(b"\n") if not l.lower().startswith(b"co-authored-by: claude"))
'callback は各メッセージを bytes として受け取り、保存するメッセージを返します。そのため、callback 内のすべての文字列には b prefix が付きます。filter-repo は、fresh clone ではない repository に対しては、--force を渡さない限り実行を拒否します。また、処理の完了時に origin remote を削除します。これにより、書き換えた履歴を誤って push し返すことを防ぎます。remote を意図的に再追加して force-push し、その後、全員に re-clone を依頼してください。各自が保持している hash はすべて、変更前のものになっているためです。
履歴の書き換えでできないことを明確にしておきます。書き換わるのは、自分の repository のコピーです。fork、既存の clone、mirror、すでにメッセージを引用している pull request ページ、先週クロールした code search index までは変更されません。漏えいした secret については、secret のローテーションが修正であり、履歴の書き換えは後処理です。disclosure trailer は secret ではありません。そのため、すべての open pull request を再構築する必要があることも含め、履歴全体を書き換えるコストと比較して判断してください。
レビュー担当者が確認したいこと
メンテナー間でこの点の意見は一致していません。削除する前に確認すべき本当の理由は、そこにあります。開示を求め、元に戻すよう依頼するプロジェクトもあります。レビュー担当者は、機械生成のパッチを通常とは異なる視点で確認するためです。一方で、変更を法的に作成したのは誰かという問題を理由に、開示を禁止するプロジェクトもあります。DCO(developer certificate of origin)を使用するプロジェクトでは、Signed-off-by: 行が必要です。これは、コードを提出する権利が自分にあることを表明するものです。不注意なメッセージフィルターを使うと、帰属情報と一緒にこの行まで削除されます。
まず CONTRIBUTING.md を読みます。プロジェクトに方針の記載がない場合は、リポジトリ内で適用するルールを1つ選び、文書化してください。コミットの半分にだけトレーラーが付く状態は、どちらの選択よりも悪い結果になります。履歴全体が、2つのプロジェクトのものに見えてしまうためです。
ノートパソコンではなくサーバー上でエージェントを実行する場合も、同じ問題が1段下の層で発生します。VPS 上で専用アカウントを使って Claude Code を実行する方法では、エージェントがアクセスできるリポジトリの範囲を決めます。コーディングエージェントがマシン外へ送信する情報では、コミットメッセージには現れないネットワークトラフィックを扱います。
FAQ
Co-authored-by Claude 用の trailer は、リポジトリの contributor 統計に反映されますか?
いいえ。GitHub は、GitHub アカウントに関連付けられたメールアドレスを通じてコミットをプロフィールに関連付け、その情報に基づいてコントリビューションを集計します。どのアカウントにも属さないアドレスは関連付けられないため、trailer によってコミットページは変わりますが、contributor 一覧は変わりません。Git 自体が trailer を読み取ることもありません。git shortlog -sn は author ヘッダーを数えるため、co-author はそこに表示されません。
trailer が付いた既存のコミットをすべて見つけるにはどうすればよいですか?
git log -i --grep='^Co-authored-by:' --format='%h %an %s' は、履歴全体から該当するコミットを大文字と小文字を区別せずに一覧表示します。新しい git では、git log --format='%h %(trailers:key=Co-authored-by,valueonly)' によって raw text の照合ではなく、git 自身の trailer parser で値を読み取ります。まだ push していないコミットだけを確認するには、range を追加します: git log origin/main..HEAD --format=%B。
すでに push したコミットから trailer を削除できますか?
はい。ただし、履歴の書き換えが必要で、影響は小さくありません。自分だけが使用する branch であれば、amend または rebase を実行してから git push --force-with-lease を実行します。共有 branch では、最初に編集したコミット以降のすべてのコミットで新しい hash が生成されるため、すべての clone と、開いているすべての pull request を作り直す必要があります。書き換えは fork、mirror、または誰かが昨日作成した clone には反映されません。
コミットメッセージに含まれる claude.ai の session link はセキュリティリスクですか?
これは credential ではありません。session へのアクセスは、URL が推測しにくいかどうかではなく、アカウントによって決まります。問題は、作業メモとして書かれた transcript を指す永続的な公開テキストになることです。Claude Code settings reference では、attribution.sessionUrl を cloud および Remote Control のコミットからその link を除外するためのキーとして説明しています。また、commit-msg hook を使うと、設定の対象外となるものからも link を削除できます。
attribution は無効にすべきですか?
これは好みではなく、リポジトリによって判断します。公開プロジェクトでは CONTRIBUTING.md に従ってください。開示を求める maintainer から、再び有効にするよう依頼される可能性があるためです。会社のリポジトリでは、trailer を残すと役立つことがよくあります。1 年後にレビューする人が、変更内容がそのようになっている理由を確認できるためです。リポジトリ全体で一度方針を決め、CI で適用してください。そうすれば、履歴の一貫性を維持できます。