ANTIGRAVITY LABJP
Articles/Tips & Best Practices
Tips & Best Practices/2026-08-06Advanced

Seven Characters Don't Only Point at Commits — Measuring When Your Agent's Recorded Hashes Stop Resolving

Short commit hashes recorded by an agent quietly stop resolving as a repository grows. Measuring where ambiguity begins, fixing the recording side, and building a batch verification gate.

Git9Antigravity CLI22Agent Operations6CI7

Premium Article

I handed the same string to two commands in a row.

$ 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'

Not a single character of the argument changed. One resolved. The other refused.

Nothing was broken in the repository. What was broken was the format of the thing that had been written down — a bare seven-character string, kept as if it were a durable reference.

Antigravity CLI recently gained prefix-based resolution of abbreviated hashes into full ones in its commit history navigation. Browsing by hand got noticeably more comfortable. Meanwhile the path where a machine writes a short hash and a machine reads it back had been rotting quietly for a long time. This was the nudge to look at it properly.

Where does ambiguity actually begin? I did not want to guess at the boundary, so I built four synthetic repositories and measured.

The same string passes one command and fails the next

Start with isolating the behavior.

I built a 40,000-commit synthetic repository and picked two colliding seven-character prefixes. One collides between a commit and a blob; the other between two commits. Each was handed to the same set of commands, and exit codes recorded.

Command1544491 (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 — resolvesexit 128 — ambiguous
git log -1 <p>exit 0 — resolvesexit 128 — ambiguous

When a commit collides with a blob, git log and the ^{commit} peel operator survive. In positions where only a committish is grammatically valid, git narrows the candidate set for you.

That turned out to be the nasty part. Only some stages of a pipeline fail. And only on runs that happen to touch a hash that happens to share a prefix with a blob. It gets filed as a flaky failure, nobody finds a cause, and it comes back.

Commit-to-commit collisions leave no escape hatch. Adding ^{commit} cannot help when both candidates are commits. That case fails honestly and consistently, which — perversely — makes it the easier one to live with.

Prefix resolution searches every object, not just commits

Sizing the prefix from the commit count was the original mistake.

A git object database keeps commits, trees, and blobs in one shared namespace. Prefix resolution scans across all of them, so what actually governs collision probability is the total object count.

The measurement environment: Linux 6.8.0-124, 4 vCPU, 3.9 GB RAM, git 2.34.1, Python 3.10.12. Repositories were generated with git fast-import using a fixed seed of 20260806. Each commit rewrites 3 files drawn from a pool of 200, which produced exactly 6 objects per commit (1 commit, 2 trees, 3 blobs).

CommitsTotal objectsImport timeColliding 7-char pairs (all objects)Colliding 7-char pairs (commits only)
1,0006,000362 ms00
5,00030,0001,483 ms21
20,000120,0004,575 ms261
40,000240,0008,660 ms1168

At 40,000 commits, commit-to-commit collisions number 8. Include blobs and trees and it becomes 116. That is 14.5 times the exposure.

If you reason from commit count alone — "we're only at 40k commits, seven characters is plenty" — you underestimate the real collision surface by nearly an order of magnitude.

The composition is worth a closer look too. Of the 116 colliding seven-character groups in that repository, 35 contain at least one commit: 27 mix a commit with a non-commit object, and 8 are commit-to-commit.

So among collisions that involve a commit at all, close to 80 percent are the "only some commands fail" variety. The kind that fails loudly enough to notice is the minority.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Git prefix resolution searches blobs and trees alongside commits, so a 40,000-commit repository showed 116 colliding 7-character pairs across all objects versus only 8 among commits
Why the same short hash succeeds with git log but exits 128 with rev-parse and cat-file, plus a per-command resolution table
A fail-closed gate that verifies recorded hashes in bulk — 11.8 ms for 300 references, 48 times faster than looping rev-parse
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Tips2026-07-05
When Your Agent's Commits Pick Up Junk Files: Fixing It With Staging Scope and a Message Convention
Agents tend to run git add -A, sweeping .bak files and caches into your history, and leave a one-word message. Here is how a staging allowlist, a preflight, and a fill-in message template stop it.
Tips2026-05-02
Pairing git bisect with Antigravity's AI to Find a Regression's Root Commit in Minutes
When something worked last week and is broken today, git bisect plus Antigravity's AI can isolate the offending commit in under thirty minutes. Here is the working split between human and AI that I have found most reliable.
Agents & Manager2026-08-05
Reading the Same History in 38 Seconds — or 0.4: Handing a Read-Only .git to Your Agent
Antigravity CLI 1.1.10 lets the sandbox read .git without write access. I built a per-session history summary two ways, measured a roughly 100x speed gap, traced it to process spawn cost, and added a guard for shallow clones that silently corrupt the numbers.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →