【ITニュース解説】git blame Says You Wrote It. Record Which Agent Did, With git notes
2026年10月30日に「Dev.to」が公開したITニュース「git blame Says You Wrote It. Record Which Agent Did, With git notes」について初心者にもわかりやすく解説しています。
ITニュース概要
`git blame`でAIが書いたコードが自分の名前で表示される場合がある。これを解決するため、`git notes`を使うと、既存コミットを改変せずに、AIエージェントやモデル、タスクといった詳細情報を後から添付できる。これにより、コードの出所を明確にし、トラブルシューティングに役立てられる。
ITニュース解説
システム開発の現場では、AIがコードを生成する場面が増えている。しかし、AIが書いたコードに後でバグが見つかった場合、その原因特定が複雑になるという課題がある。例えば、数週間後にログイン機能のバグが発覚し、問題のコード行をgit blameコマンドで確認すると、自分の名前が「ログインテストの不安定さを修正」というコミットに表示されることがある。しかし、そのコードを実際に書いたのは自分ではなく、過去に使用していたAIツールだった、という状況は珍しくない。どのAIモデルを使い、どれくらいの労力をかけたのか、当時のタスク内容は何だったのか、といった情報が残っていないと、デバッグや再発防止策の検討は非常に困難になる。
このようなAI生成コードの出所を明確に記録する方法として、まず「コミットトレーラー」が挙げられる。コミットトレーラーとは、コミットメッセージの末尾に、AIエージェントの名称やモデルなどの情報を追加する手法のことだ。これはAIツール自身が自動でコミットに追加することも可能である。しかし、コミットトレーラーはコミットが作成される前にメッセージに含める必要がある。もしコミットが作成された後にトレーラーを追加しようとすると、それはコミットメッセージの変更にあたり、コミットの識別子であるSHA(Secure Hash Algorithm)が書き換えられてしまう。一度書き換わったコミットのSHAは新しいものになり、もしそのコミットが既にマージされているブランチに含まれる場合、他の開発者に影響を与えないようにするには「強制プッシュ」が必要となる。これはチーム開発においては避けるべき操作であり、履歴の整合性を保つ上で問題となる。
そこで本記事では、コミットの履歴を書き換えることなく、AI生成コードの情報を追加できるgit notesという機能を紹介する。git notesは、Gitのオブジェクト、つまりコミットそのものに手を加えることなく、追加のデータを関連付けることができる機能である。これにより、AIエージェントの種類、使用したAIモデル、投入した労力、元のタスク内容といった情報を、コミットSHAを変えずに後からでも付加できる。
git notesの具体的な使い方を説明しよう。
まず、AIが作成したコミットを選び、それに対してノートを作成する。ノートはkey: value形式で1行ずつ記述する形式が推奨される。例えば、printfコマンドで整形した文字列をgit notes --ref=agents add -F - HEADコマンドにパイプで渡すことで、現在のHEAD(最新のコミット)にノートを追加できる。ここで重要なのは--ref=agentsというオプションだ。これは、AIに関するノートをrefs/notes/agentsという専用の参照(リファレンス)に保存することを意味する。Gitにはデフォルトでrefs/notes/commitsというノート用の参照があるため、これと衝突しないように専用の参照を用意するのが良い。これにより、他のツールが利用している可能性のあるデフォルトのノート参照を汚染することなく、AIノートだけを独立して管理できる。addコマンドは、既にノートが存在するコミットにはノートを追加せず、上書きするには-fオプションが必要だ。
作成したノートは、git notes --ref=agents show HEADで簡単に読み出せる。また、git log --notes=agentsコマンドを使えば、コミットメッセージの下にノートも一緒に表示できる。毎回このオプションを打つのが面倒な場合は、git config notes.displayRef refs/notes/agentsと設定することで、git logを通常のオプションなしで実行しても、自動的にAIノートが表示されるようになる。問題のログインバグに戻り、git blameで特定したコミットのSHAを使ってgit notes --ref=agents show "$sha"を実行すれば、そのコミットに関するAI情報をすぐに確認できる。さらに、git log --notes=agents --grep='agent: codex'のように、ノートの内容に基づいてコミット履歴を検索することも可能だ。
git notesは便利だが、ノートの参照はデフォルトではリモートリポジトリにプッシュされない。そのため、チームメンバーと共有するには明示的にプッシュする必要がある。git push origin refs/notes/agentsコマンドで、ローカルのAIノート参照をリモートリポジトリに送信できる。フェッチ(リモートからの取得)の際は少し注意が必要だ。もしgit fetch origin refs/notes/agentsのように直接フェッチしてしまうと、リモートのノートがローカルのノートを上書きし、まだプッシュしていないローカルの変更が失われる可能性がある。これを避けるため、git fetch origin refs/notes/agents:refs/notes/origin/agentsでリモートのノートを一時的なローカル参照に取得し、その後にgit notes --ref=agents merge -s cat_sort_uniq refs/notes/origin/agentsコマンドを使ってマージすることが推奨される。cat_sort_uniqというマージ戦略は、同じコミットに対して複数のノートが存在した場合、それらを連結し、各行をソートして重複を排除する。この特性から、ノートをkey: value形式で記述しておくことが、衝突を適切に解決するために重要となる。
Gitのリベースやコミット修正(git commit --amend)は、既存のコミットのSHAを変更する操作である。デフォルトでは、これらの操作を行うと元のコミットに付いていたノートは新しいコミットには引き継がれず、古いコミットに残ってしまう。しかし、git config notes.rewriteRef refs/notes/agentsと設定することで、これらの操作時にAIノートを新しいコミットに自動でコピーさせることが可能だ。この設定を一度行えば、git commit --amendやgit rebaseの際にノートが自動的に新しいコミットに引き継がれるようになる。ただし、git cherry-pick(他のブランチから特定のコミットを選んで取り込む操作)の場合、ノートは自動でコピーされない点には注意が必要だ。また、リベースによって複数のコミットが一つにまとめられる(スカッシュされる)場合、notes.rewriteModeの設定によって、デフォルトでは複数のノートが連結されて一つにまとめられたコミットに付与される。
各コミットに手動でノートを追加するのは現実的ではない。最も効率的なのは、AIが生成したコードを含むブランチがマージされた直後に、そのブランチ内の全てのコミットに対して一括でノートを適用することだ。記事では、agent-noteというシェルスクリプトの例が紹介されている。このスクリプトは、指定されたコミット範囲に対して、AIエージェント、モデル、労力、タスク内容をノートとして追加する。既にノートが設定されているコミットはスキップするため、複数回実行しても安全だ。例えば、main@{1}..mainという範囲指定を使うことで、直前のマージでmainブランチに追加されたコミット群を正確に特定し、そこにまとめてノートを付与できる。その後、忘れずにgit push origin refs/notes/agentsでノートをリモートにプッシュする。
しかし、git notesにも限界と注意点がある。まず、ノートは単なるラベルであり、「証明」にはならない。git notesコマンドにはノートに署名する機能がなく、ノートの変更履歴は通常のGitコミットとして記録されるものの、権限を持つ人であれば誰でもその履歴を強制的に書き換えたり、ノート自体を変更・削除したりできる。本当に誰も改ざんできない記録が必要な場合は、コミットトレーラーをコミット作成時に含め、コミット自体に署名するしかない。また、ノートの内容は手動またはスクリプトで入力されるため、入力された情報が間違っていれば、ノートも間違った情報として記録されてしまう。さらに、GitHubのWeb UIでは2014年以降、Git notesの表示がサポートされていない。これは、プルリクエストのレビュー画面など、WebベースのインターフェースではAIノートが見られないことを意味し、ターミナル上でしか確認できないため、情報の共有や確認には一手間かかる可能性がある。
そして最も重要なのは、「習慣化」が必要なことだ。git notesはデフォルトではフェッチされず、スカッシュマージやリベースマージでは元のコミットにノートが残ってしまうことがあり、チェリーピックではノートがドロップされる。ステップ2で紹介したプッシュ、フェッチ、マージのプロセスを、開発フローに組み込み、定期的に実行する習慣がなければ、ノートは最新の状態に保たれず、やがて機能しなくなるだろう。
これらの課題を理解し、適切な運用を行うことで、git notesは非常に強力なツールとなる。各コミットにAIエージェントのタスク情報が付与されていれば、git log --notes=agents --grepコマンドを使うことで、どのタスク説明や設定で生成されたコードが長期的に安定したのか、あるいは後から修正が必要になったのか、といった分析が可能になる。これは、AIモデルの選定やプロンプトエンジニアリングの改善に大いに役立つだろう。開発者は、AIと協力してコードを生成する中で、その「出所」を記録することで、より堅牢で保守しやすいシステム開発を目指せるのだ。