◉ANTIGRAVITY LABEN
記事一覧/Tips & 活用術
✦ Tips & 活用術/2026-08-06上級

7桁ハッシュが指しているのはコミットだけではない — エージェントの記録が解決不能になる境界を測る

7桁の短縮ハッシュが git log では通るのに git show では落ちる——プレフィックス探索がオブジェクト全体に及ぶことが原因でした。衝突境界の計算、記録側を完全ハッシュに直す設計、散らばったログを検査する fail-closed ゲートを紹介します。

Git13Antigravity CLI42エージェント運用20CI11

✦ プレミアム記事

同じ文字列を、続けて 2 つのコマンドに渡したときのことです。

$ git log -1 --format=%H 1544491
154449150bd5e4d3256ba9511e2cc9def88872a0

$ git show --quiet 1544491
error: short object ID 1544491 is ambiguous
hint: The candidates are:
hint:   154449150 commit 2023-12-12 - change 39719 12e206e9
hint:   1544491a9 blob
fatal: ambiguous argument '1544491'

引数は 1 文字も変えていません。片方は解決し、もう片方は落ちます。

リポジトリが壊れているわけではありませんでした。壊れていたのは、記録として書き残された「7 桁の文字列」という形式のほうです。

人が履歴を辿るときの 7 桁は、いまも便利です。ところが、機械が書いた短縮ハッシュを機械が読み戻す経路は、以前から静かに腐り続けていました。今回はそこを、数えて確かめることにしました。

どこから曖昧になるのか。境界を勘で決めたくなかったので、合成リポジトリを 4 サイズ作って測っています。

同じ文字列が、あるコマンドでは通り、別のコマンドでは落ちる

まず現象の切り分けからです。

40,000 コミットの合成リポジトリを用意し、7 桁が衝突しているプレフィックスを 2 種類選びました。片方は commit と blob の衝突、もう片方は commit 同士の衝突です。それぞれに同じ文字列を渡して、終了コードを取っています。

コマンド1544491(commit + blob)6ce18aa(commit + commit)
git rev-parse <p>exit 128 — ambiguousexit 128 — ambiguous
git cat-file -t <p>exit 128 — ambiguousexit 128 — ambiguous
git show --quiet <p>exit 128 — ambiguousexit 128 — ambiguous
git rev-parse <p>^{commit}exit 0 — 解決するexit 128 — ambiguous
git log -1 <p>exit 0 — 解決するexit 128 — ambiguous

commit と blob が衝突しているとき、git log と ^{commit} は生き残ります。文脈上コミットしか受け付けない位置では、git が候補をコミットに絞り込んでくれるためです。

これが厄介でした。パイプラインの一部の工程だけが落ちます。しかも落ちるのは、たまたま blob と衝突した特定のハッシュを踏んだ実行だけ。再現性のない不具合として処理されて、原因が特定されないまま何度も戻ってきます。落とし穴としては、かなり質の悪いほうでした。

commit 同士の衝突になると、逃げ道はありません。^{commit} を付けても候補が 2 つとも commit なので絞り込めません。ここは素直に落ちてくれるぶん、まだ扱いやすい相手です。

プレフィックスの探索範囲は、コミットではなくオブジェクト全体

必要な桁数を「コミット数」から見積もっていたのが、そもそもの誤りでした。

git のオブジェクトデータベースには commit・tree・blob が同じ名前空間で同居しています。プレフィックス解決はそこを横断して探すため、衝突確率を決めるのは総オブジェクト数のほうでした。

計測環境は Linux 6.8.0-124 / 4 vCPU / 3.9 GB RAM、git 2.34.1、Python 3.10.12。git fast-import で合成リポジトリを作り、シードは 20260806 に固定しています。200 ファイルのプールから 1 コミットあたり 3 ファイルを書き換える構成で、コミットあたりちょうど 6 オブジェクト(commit 1 + tree 2 + blob 3)が生まれました。

コミット数総オブジェクト数生成時間7 桁の衝突ペア(全体)7 桁の衝突ペア(コミット同士)
1,0006,000362 ms00
5,00030,0001,483 ms21
20,000120,0004,575 ms261
40,000240,0008,660 ms1168

40,000 コミットの時点で、コミット同士の衝突は 8 組。ところが blob と tree を含めると 116 組でした。14.5 倍です。

コミット数だけを見て「うちはまだ 4 万コミット、7 桁で十分」と判断していると、実際の衝突面積を一桁近く見誤ることになります。

衝突している集合の内訳も見ておきます。40,000 コミットのリポジトリで 7 桁が衝突しているグループは全体で 116 組。そのうちコミットを 1 つ以上含むのは 35 組で、内訳は commit と非 commit(blob・tree)の混在が 27 組、commit 同士が 8 組でした。

つまりコミットが絡む衝突の 8 割近くが、前節の「一部のコマンドだけ落ちる」型です。落ちてくれれば気づけるほうの衝突は、むしろ少数派でした。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦git のプレフィックス解決は commit だけでなく blob と tree も探索するため、40,000 コミットのリポジトリでは 7 桁の衝突がコミット同士 8 組に対し全体では 116 組に達しました
✦同じ短縮ハッシュが git log では通り rev-parse や cat-file では exit 128 で落ちる理由と、コマンド別の成否判定表
✦記録済みハッシュを一括検査する fail-closed ゲートの実装。300 件で 11.8 ms、逐次 rev-parse の 48 倍の速さです
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

✦ Tips & 活用術2026-10-30
Linux で通った sed -i が iMac で止まった夜。エージェントの手順書を手元で動かす前の確かめ方
Linux の環境で動いた sed -i の手順を iMac で実行すると、置き換えが止まったり、バックアップが散らかったりします。GNU 版で再現した出力と、どちらでも動く書き方、実行前の確かめ方をまとめました。
⚙ AIツール2026-09-15
役割で分けるのをやめた日 — Antigravity CLI と Claude Code の預け先を決める3つの問い
無人で回していた処理が承認待ちのまま黙って止まりました。二つのエージェント CLI を得意分野で分けるのをやめ、承認の境界で振り分け直すまでの記録と、判断に使っている3つの問いを書き残します。
⬡ 連携・プラグイン2026-09-12
Antigravity CLI 1.1.28 で print-timeout 超過が成功終了になりました — 無人実行の判定を見直す
1.1.28 から --print-timeout の超過は例外ではなく、部分出力を返しての正常終了になりました。外部 URL の取得も既定で承認待ちです。終了コードだけで成否を決めている無人実行を、どう組み直したかを書き残します。