Gitのmainに謎ファイルが18個あった。でも、消さずに本番デプロイした

Gitの未追跡ファイルを残したまま安全に本番デプロイする流れを表現した水彩画風イラスト AI

昨日、Knowledge MCPを本番環境へデプロイしようとしたとき、preflightで止まりました。理由の一つが、Gitのmainに18個のuntrackedファイルが残っていたことです。

Gitを使っている人なら、@@INLINE0@@ に @@INLINE1@@ がずらっと並んでいる状態を見たことがあると思います。Gitから見ると「管理していないファイル」なので、きれいなmainを前提にしたデプロイ処理からすると邪魔です。実際、当時の私のシステムもmainが完全にcleanでなければ本番デプロイを許可しない作りになっていたので、18個のファイルを検出して処理を止めました。

ここで一番簡単なのは、邪魔なファイルを消してしまうことです。でも、自分のPersonal AI PlatformをAIに運用させるうえで、これはかなり嫌な挙動です。「何のファイルか分からないけれど、デプロイの邪魔だから消しました」だけはやってほしくない。

untrackedだからといって、ゴミとは限りません。誰かがまだcommitしていない作業ファイルかもしれないし、一時的な調査スクリプトかもしれない。別のAIエージェントが作業中に生成したものかもしれません。特に今の環境では複数の開発作業が並行して進むので、「Git管理外=不要」と判断するのはかなり危険です。

そもそも、なぜuntrackedファイルがあると危ないのか

最初の実装ではかなり単純に、git status が完全にcleanかどうかを見ていました。mainがorigin/mainと一致していて、作業ツリーにも何もなければOK。それ以外は停止です。

安全側に倒すなら、これは正しいです。問題は、本当に本番デプロイに影響する変更と、そこに置いてあるだけのファイルを区別していないことでした。

今回のKnowledge MCPのデプロイは、現在mainのディレクトリをそのまま本番へコピーする仕組みではありません。承認された特定のGit SHAを指定し、そのSHAから独立したcheckoutを作って、そこからデプロイします。つまり、Gitに一度もcommitされていないuntrackedファイルは、そもそもデプロイ元には入りません。

例えばmainに、

?? scripts/test_something.py

というファイルが置いてあっても、承認対象がGit SHA @@INLINE0@@ なら、そのSHAの世界にはこのファイルは存在しません。別の場所に@@INLINE1@@だけをcheckoutしてデプロイすればいい。

そこで、「mainにファイルがあるか」ではなく、そのファイルが承認したコードを変えているかを見るようにしました。

現在のpreflightでは、main自身がorigin/mainを正確に追跡していることを確認したうえで、追加で存在するものがすべて ??、つまりuntrackedだけならデプロイを許可します。一方、Git管理下のファイルが1文字でも変更されていれば止まります。mainがorigin/mainより1 commit先に進んでいる、といった状態でも止まります。

この違いはかなり大きいです。

「きれいにする」のではなく「影響しないことを証明する」

最初に18個のuntrackedファイルを見たときは、「これをどう片付けるか」という問題に見えました。でも途中から、そもそも発想が逆だと気付きました。

片付ける必要はない。デプロイに混ざらないことが保証できればいい。

人間が自分のPCで作業しているなら、「これ昔のファイルだな」と確認して消すこともできます。でもAIエージェントに同じことをやらせるとなると、その判断にはかなり高い確信が必要です。所有者が分からないファイルを消すより、そのファイルには一切触らず、安全な経路だけを使って目的を達成するほうがいい。

今回の修正では、untrackedしかない場合を許容するだけでなく、テストも追加しました。untrackedだけなら通る。trackedファイルに変更が混ざっていれば止まる。mainがorigin/mainよりaheadしていても止まる。この境界をコードとして固定しています。

結果として、18個のファイルはそのまま残し、本番デプロイには承認済みのexact SHAだけを使うことができました。

AIコーディングで意外と大事なのは「他人の状態を壊さない」ことかもしれない

AIコーディングというと、どうしても「どれだけ速くコードを書けるか」「どこまで自律的に修正できるか」が目立ちます。でも、複数のAIエージェントを同時に動かしていると、別の難しさが出てきます。

自分の作業だけを見れば正しい行動でも、別の作業を壊す可能性があるからです。

「mainをcleanにしてください」という目標だけを与えられたAIなら、untrackedファイルを全部削除すれば最短です。目的は達成できます。でも、その中に別作業の途中ファイルがあったら困ります。

これは以前の記事で書いた「承認にも賞味期限が必要」という話とも少しつながっています。AIに強い権限を渡すほど、「賢く判断してくれるだろう」ではなく、何をしてはいけないかを構造で決めておいたほうがいい。

今回なら、

「本番デプロイを通すためにmainをcleanにする」

ではなく、

「承認されたGit SHAだけからデプロイし、それ以外のローカル状態には触らない」

と定義するほうが安全です。

昨日のKnowledge MCPのデプロイでは、最初に18個の謎ファイルがblockerとして出てきました。でも最終的にやったのは、それらを整理することでも削除することでもありませんでした。

その18個を無視しても安全なデプロイ経路を作ることでした。

AIにサーバー管理まで任せ始めると、こういう地味な設計が結構効いてきます。「邪魔なものを消して先へ進むAI」より、「他人のものには触らずに別の安全な道を探すAI」のほうが、私は運用を任せやすいと思っています。

コメント

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