未来を形作るテクノロジーの深掘り記事。

gitが壊れるとき:1日3万マージのモノレポから学んだこと

極端なマージ頻度でGitのモノレポ運用が壊れる典型パターンを解説。常時オンラインのクライアントとサーバー側コミットの教訓。

広大なファイルボックスの保管庫で、チェックカウンターに群がるロボット配達員のイラスト。
Gitは、すべてのクライアントがアーカイブ全体を持っていると想定しています。その前提は、毎秒何千ものクライアントが列を作るまでは問題ありません。

git モノレポを運用しているなら、いつかどこかで車輪が外れる地点が訪れます。Anthropicの場合、その数字は1日あたり約3万マージ、100 GBのmainブランチ履歴、そして1日約2,500万回のCIチェックアウトでした。素朴にフェッチすると、1日で600ペタバイト超のgitトラフィックになる計算です。毎日です。彼らの答えは、5か月かけて独自のバージョン管理システムを書くことでした。あなたの答えはそれであってはなりません。ただ、途中で彼らが踏んだ失敗は、規模が10分の1のチームでも私が毎回目にするものと同じなので、順に見ていきましょう。

ミス1:集中型のワークフローを分散型のように扱う

Gitの中核となる設計上の賭けは分散化です。すべてのcloneは完全なリポジトリで、履歴も、オブジェクトストアも全部そろっていて、オフラインでも完全に動きます。この賭けがgitを世界標準にし、多くのリポジトリではいまも正しい選択です。ただ、ほとんど誰も認めたがらない事実があります。実際にはほぼ誰もgitをそんな使い方をしていません。組織にはGitHubやGitLabの権威あるリモートが1つあり、開発者は絶えずpushとpullし、CIランナーは定義上つねにオンラインです。分散システムの服を着た集中型システムを動かしていて、分散型のコストだけは払っている状態です。CIジョブは読むことのない履歴を毎回引きずり、エージェントのサンドボックスは不要なpackfileを展開しています。

これがAnthropicの再設計から得られる最初の本当の教訓です。彼らは一歩引いて見直したとき、クライアントが「定義上つねにオンラインのエージェントとジョブ」であることに気づき、常に到達可能なサーバーを前提に設計しました。クライアントはあえて愚直にしました。有界なローカルキャッシュ、ディスク上のワーキングコピー、ファイルシステムウォッチャーだけです。blame、diffの計算、マージはサーバーが担当します。これはGoogleがPiperで、MetaがSaplingで到達したのと同じ結論です。gitに反対しているわけではなく、アーキテクチャは20年前にツールが想定した負荷ではなく、実際の負荷に合わせるべきだという認識です。セキュリティツールでも同じパターンを見てきました。チームはオフラインでも動くエージェント構成を導入し、そのあと「オフラインになることが実際にはまったくない」環境で動かして、同期レイヤーが悪夢になったと首をかしげるのです。

チームへの教訓は「VCSを作れ」ではありません。前提を洗い出すことです。実際に依存しているgitの性質を書き出してください。オフライン作業は必要か?本物のforkは使っているか?暗号署名付きコミットは必要か?正直な答えが「リモートは1つ、常にオンライン、CIがすべてを担う」なら、存在しない分散ワークフローに最適化するのをやめて、チェックアウトとクエリのコストを最適化し始めましょう。

ミス2:ミラーとシードで規模の問題を覆い隠す

大規模リポジトリを扱うチームは、必ず同じ苦労の段階を通ります。最初は shallow clone。次にsparse checkoutとpromisor remote。その次は社内gitミラー、そしてCIジョブが先端に近い状態から起動できるよう、Blobストレージに置くスナップショットの「シード」です。Anthropicはこれらすべてを使い、ピーク時には数百の社内ミラーがありました。そして失敗のしかたはいつも同じです。回避策は派手には壊れず、静かに腐っていきます。シードは更新と更新の間にmainの先端からどんどん離れていきます。部分クローンは git blame や git log --follow を紛らわしい形で壊します。履歴が切り詰められているせいで、誰かのbisectが静かに誤った結果を返すこともあります。インシデントのレビューまで誰も気づきません。

一番眠れなくなるのはこの最後の点です。部分履歴の正しさのバグは、まさに「システムが保証すると思っていること」と「実際にやっていること」のあいだの隙間に潜む類の、微妙な誤りです。shallow cloneは深さを超えたblameを要求されてもエラーを出しません。ただ部分的な答えを返すだけです。自動revertパイプラインがその答えを信頼していたら、間違った変更を自信満々にrevertする機械を作ってしまっていることになります。

  • shallow cloneは履歴に依存するツール(blame、bisect、merge-base)を、大きくではなく静かに壊します。
  • スナップショットシードはmainの先端からずれていきます。マージ頻度が高いほどずれも速く、負荷が上がったまさにそのときに回避策が劣化します。
  • ミラー群は運用面の表面積を増やします。状態を持つコピーが数百あり、それぞれが独立して遅延、破損、ディスク枯渇を起こしえます。
  • 履歴の意味に触れる回避策はどれも回帰テストが必要です。さもないとインシデント対応中に痛い目を見ます。

Anthropicの規模での解決策は構造的なものでした。リポジトリの完全なコピーはサーバー上を含めてどこにも存在せず、すべてがコンテンツアドレス指定で水平にキャッシュ可能になっています。あなたの規模では、もっと控えめな対応で十分です。リポジトリのフルまたはほぼフルのコピーを持つマシンがいくつあるかを測り、それぞれのずれや故障モードを正直に把握しましょう。

ミス3:CIジョブごとにリポジトリのコピーを持たせてしまう

CIのフリートについて考えてみてほしい質問があります。そのジョブのうち、ワーキングコピーが必要なものはいくつあるでしょうか。Anthropicが自前のシステムを作ったあとの答えは「想定よりずっと少ない」でした。コミットと、そのマージベースとの差分、ファイルのblame、特定パスに触れたコミット一覧が必要なジョブは、APIでサーバーに直接問い合わせられます。cloneもfetchもディスクも不要です。自動bisectやrevertパイプラインは、この安価でプログラムから叩けるアクセスなしには「大規模では現実的でない」とのことでした。私もそう思います。ローカルcloneの上で同じパイプラインを動かそうとして、fetch時間に溺れたチームを何度も見てきたからです。

この原則はソースコード管理をはるかに超えて通用します。チェックアウトは既定ではなく、高コストな例外として扱ってください。ジョブがファイルを必要とする場合でも、sparseや仮想化されたチェックアウトを使えば、要求されたディレクトリだけ、あるいは実際に読むファイルだけを展開でき、コストを桁違いに下げられます。Anthropicのフェッチプロトコルは、gitのネゴシエーションを丸ごと捨てました。クライアントは必要な不変のツリーとblobを指定し、どのキャッシュでも応答でき、全体としては、クライアントごとにpackfileを計算する賢いサーバーではなく、階層化されたCDNのように振る舞います。CI負荷でgitサーバーが溶けるのをプロファイルしたことがあれば、なぜそれが重要かお分かりでしょう。packfileの生成がCPUを食うのは、プロトコルがサーバーに「各クライアントがすでに持っているものとの差分」を計算させるからです。

クライアントが常にオンラインで権威あるコピーが1つだけなら、あなたが維持しているローカルcloneはすべて、フル料金を払っているのに結局キャッシュとしての振る舞いしか得られていないキャッシュです。

ミス4:コミットのコストをリポジトリのサイズに比例させてしまう

彼らの設計で最も面白いエンジニアリング上の判断は、changesetです。gitのコミットはリポジトリ全体の状態を表すツリーを指しますが、彼らのchangesetは、最初の親に対して変更されたファイルの一覧と、Blobストレージへのコンテンツアドレス指定ポインタだけを記録し、それをwrite-ahead logに追記します。受け入れるpackfileもなく、ロックもなく、サーバー間の調整もありません。ブランチやタグといったrefは意図的に軽視されています。「すべてのサーバーが合意しなければならないグローバル状態は、迫りくるスケーリング問題だから」です。refの移動は、コミット作成から切り離された、Spannerの1行に対するcompare-and-swapです。

コンベアベルトを流れる荷物が、発光するログと派生データ構造へ送られる様子を描いたスタイライズされたイラスト。
変更されたものだけをwrite-ahead logに記録し、blameやパス履歴、グラフインデックスなどのほかのデータは、そこから遅延的に導出します。

その発想に付随するのが「派生データ」という考え方です。blameインデックス、パス履歴、コミットグラフのスキップリストなどを、各changesetの親から再帰的に計算し、すべて一つの汎用的な仕組みで扱います。型ごとに即時計算するか遅延計算するかを選べ、クライアントに手を加えずに新しいインデックス型を追加できます。これはイベントソーシングされたシステムにとって本当に良いパターンです。監査ログのパイプラインにも同じ形を勧めてきました。追記専用のログが真実であり、あらゆるクエリ用の構造は再構築可能な投影です。誰かがその仕組みの外で投影を手で管理し始めた瞬間に、ずれが生じます。

セキュリティの観点からの一つの注意点です。集中化を懸念するコメントには、真剣に受け止める価値があります。コミット、マージ、履歴クエリがすべて存在する単一のサーバー側システムは価値の高い標的であり、「すべてを支配する一つのリポジトリ」への書き込み権限を持つAIエージェントは、リスクを著しく集中させます。Anthropicは並行して「リッチなソースコード管理IAMシステム」を構築しており、その詳細はデータ構造そのものより重要です。集中化するなら、被害範囲の計算が変わります。初日から、3四半期目ではなく、分離、エージェントごとの認証情報、監査を予算に組み込んでください。共有インフラ上で状態を持つエージェントを動かしているチームは、すでにこの痛みを知っています。

ミス5:1日3万マージ=1日3万の良い判断、と思い込むこと

エンジニアリングは見事です。問題は、そこを何が流れるかです。ある実務者は率直にこう言っていました。AIが生成したコードのレビューをやめると、そのたびに「後で不出来な代物を見つける」。毎回見つかるわけではないが、十分な頻度なので、すべてのレビューをやめられない、と。この的中率を1日3万マージにかければ、Anthropicが「レビュー済みの大量のコードを管理し、着地させる新しい方法」、つまりレビューの対象範囲、ランディングキュー、自動revertパイプラインを作る必要があった理由が分かります。VCSがプロダクトだったわけではありません。着地パイプラインこそがプロダクトでした。ソースコード管理がボトルネックになったのは、その前段のレビュー能力がボトルネックになった後のことです。

彼らの苦労話には率直な細部も埋もれています。プロジェクトのエンジニアたちは、自分の役割の多くをコーディングエージェントに「ノー」と言うことだと語っていました。手で書いたプロトタイプの取り込みパイプラインは、より新しいモデルがメモリ使用量を20分の1、速度を4倍にして書き直すまでは問題ありませんでした。ただ、そこにたどり着くには、何を受け入れるかを判断する審美眼を持った人間が必要でした。これは私が見てきたことすべてと一致します。AIはエンジニアの仕事を書くことからレビューすることへと移し、レビューのスループットが今や希少資源になっています。以前にも書きましたが、レビューの層が増えるほどチームは遅くなるのです。しかし難しいのは、エージェントが生成したコードでは、レビューの層を減らすのも安全ではないことです。必要なのは、レビューを減らすことではなく、より良いレビューツールです。

実際にやるべきこと

あなたはAnthropicではありません。彼らのようなトークン予算はなく(本人たちもそう認めています)、1日2,500万回のチェックアウトもありません。しかしAIコーディングツールは誰のマージ頻度も押し上げていて、負荷の圧力は予測可能な順序でやってきます。私が従う操作の順序は次の通りです。Priyaの「後悔最小の法則」に沿ってどうぞ:

  1. まず測定する。 1日のチェックアウト数、CIジョブごとの取得バイト数、リポジトリの完全コピーを持つマシンの数を数えましょう。規模の問題より前に、無駄の問題を抱えている可能性が高いです。
  2. 不要なチェックアウトをなくす。 インフラに金をかける前に、メタデータに関する問い合わせ(差分、blame、祖先関係)をAPIに移しましょう。GitHub/GitLabのAPI、または薄い社内サービスでかまいません。
  3. sparseとpartialクローンを安全に使えるようにする。 bisect、blame、revertのツールをshallow cloneに対して明示的にテストするか、自動化からは禁止してください。
  4. 可能な場面ではCIをサーバー側・不変オブジェクトのフェッチ方式にデフォルト設定し、ミラー群は複利で増えていく技術的負債として扱いましょう。
  5. リポジトリ形式ではなく、着地パイプラインに投資する。 エージェント規模の開発で最初に壊れるのは、レビュー能力、マージキュー、自動revertです。
  6. その後で初めて、別のVCSアーキテクチャを検討する。 Saplingはオープンソースで、自前でVCSを書かなくてもクライアント・サーバー型の恩恵の大半が得られます。

ここでの最も深い教訓は、gitについてではありません。どのツールも、ワークロードに関する前提をエンコードしているということです。オフラインの人間、一度に一つのコミット、レビューされるより遅く書かれるコード。こうした前提が、今まさにエージェントによって、インフラでも、レビューでも、セキュリティ境界でも崩されています。勝ち残るチームは、すべてをゼロから作り直すチームではありません。どの前提が最初に崩れたかに気づき、まさにそれを直したチームです。