‹
TS
Textsplain
explained in texts
Wednesday, October 14, 2026 · 9:41 AM
Fictional dialogue · about 10 min
Leena, a distributed systems engineer
ok i use Git every day. how do you reach the point where you decide to replace the whole thing
start with the workload. Anthropic reports about 2,500 daily merges in May 2026, over 30,000 in September [1]
and around 25 million CI checkouts daily, with main's history almost 100 GB [1]
they'd already tried Git's standard workarounds [1]
damn. i was picturing some annoying pushes and a slow GitHub page
picture a library instead. you need one page, but your task starts by setting up a personal library branch
that's a useful deal when you'll spend months reading there. expensive when you need one page, once
so each little CI job is getting its own library setup
that's the question to keep asking: what does this job actually need, and what are we making it prepare first
we're going to separate the article's reported facts from some made-up examples that explain the design
good because i know the commands but the internals get fuzzy pretty fast
source control gives versions stable identities, records how versions relate, and lets people combine their work
those are the needs. the placement of the data, and who computes answers, are design choices
Git feels like the default answer to all of that
Git gives you a local repository. with an ordinary full clone, much of your work can happen offline [2]
you can inspect history and make commits without asking a central service for permission each time [2]
the local working files and the repository's stored history are different things [2]
so deleting a file from my checkout doesn't immediately delete every previous version
right. your checkout is the editable view. repository objects let Git reconstruct recorded versions [3]
think of the files in your editor as the book open on your desk. the archive sits behind it
why would that suddenly become bad when agents show up
imagine a developer using one checkout all week, then imagine disposable jobs constantly opening new workspaces
in that second setup, preparation cost repeats. even a cheap setup step deserves attention if repeated constantly
an agent can also ask a tiny question: which files changed? does this revision descend from that one?
and i'd probably run git diff or git merge-base in its workspace
yes. for the hypothetical job, ask whether a workspace is necessary just to answer a history question
a service could return the answer directly. then the job downloads an answer instead of preparing an archive
but Git already has shallow clones. this feels like a solved problem
it has useful knobs. a shallow clone limits the history brought down [7]
a partial clone can leave file-content objects on the server until they're needed [7]
those solve different kinds of excess. it helps to know which bytes you're avoiding
i definitely mix up partial and sparse
sparse checkout limits which tracked files appear in your working tree [8]
for an invented repo, you might select payments/ and shared/, leaving unrelated directories out of your editor
a shallow clone asks for less history. sparse asks for fewer working files. partial asks for fewer stored objects
so sparse alone doesn't guarantee i downloaded less history
exactly. a working-tree view and the underlying object download are separate concerns [7][8]
before changing tools, measure clone time, fetch time, checkout time, and the commands your jobs actually run
otherwise you might optimize the emptying of a directory while the real delay is fetching objects
ok. what's Scion actually changing then
Scion assumes online clients. servers do commits, merges, rebases, and history queries; clients keep bounded caches [1]
changesets are write-ahead-log entries: first-parent file edits plus content-addressed blob pointers [1]
derived indexes answer history and blame. refs move separately via compare-and-swap in Spanner [1]
i need like half those words explained
fair. start with a blob: file contents stored as an object. a tree maps names to blobs and subdirectories [3]
a Git commit points to a tree and records its parent relationships, author information, and message [3]
following those links tells you what the recorded project looked like
wait. does a Git commit copy the entire repo every time
unchanged content can be reused. Git's snapshot model doesn't require storing another copy of every file [2][3]
in a tiny example, you edit README. the new revision can reuse the existing content object for config.json
the snapshot describes the whole version while the storage shares unchanged pieces
that matters. otherwise this would sound like they discovered only saving changed files
yep. keep the logical model separate from the physical bytes
imagine 2 notebook pages. one says what every chapter currently contains, using pointers to existing pages
the other lists edits since the previous entry. each approach can reuse stored content
so a changeset is closer to that second page
that's the mental model. use it to reason about costs, without assuming either representation wins everywhere
a change list makes recording a small edit look simple. reconstructing a full view still needs a plan
couldn't you just replay every change from the beginning
in our toy system, sure. now imagine doing that whenever you ask who changed a line
you would repeatedly redo old work. a saved index can help you skip directly to a useful answer
PostgreSQL's materialized views illustrate the general idea: store a computed result so reads can be faster [11]
like my expense app storing a balance instead of summing every transaction on each page load
yes, as long as you still know what the underlying transactions say
that example also exposes the hard part: keeping the saved answer consistent with its inputs
PostgreSQL explicitly calls out the freshness tradeoff for materialized views [11]
does derived mean it's allowed to give stale answers
no. derived tells you where the data comes from. freshness is a separate guarantee
imagine an index keyed by a specific revision. its answer should describe that revision, even after main moves
that differs from a dashboard promising the latest total while refreshing once a day
what's the write-ahead log buying you here
a log records changes durably before other representations finish catching up. SQLite documents this pattern [12]
in a hypothetical service, you accept an entry, then update a searchable view from that durable record
if the view-building process crashes, the original entry gives you a place to resume or rebuild
content-addressed means the filename is a hash?
the identifier comes from the stored content. Git already uses content-addressed objects [3]
imagine two workers requesting the same immutable content identifier. both should get the same bytes
ask for a mutable name like latest-config and you're asking a different question
because latest could change between the requests
yep. a revision identifier lets you specify a version. a moving name needs a decision about current state
this distinction is useful whenever you cache data: cache a particular version, then separately resolve what's current
now the caches make sense. what's their actual setup
fetches pass through node daemons, regional caches, then authoritative servers backed by Spanner and cloud storage [1]
sparse and virtual checkouts request needed objects [1]
no complete repo lives on any server; no packfiles. commit work scales with changed files, not repo size [1]
show me one actual job in that kind of system
invented example: a test worker needs payments/test.py and shared/currency.py at revision R
first it resolves the requested paths for R. then it obtains those files' content objects
if its machine already has an object, reuse it. otherwise ask the next service in the chain
could a job skip even those files
sure, in our example a policy checker only wants the list of changed paths
it could request that list and evaluate it. writing source files to disk would add no value for that task
a compiler has different needs. classify consumers instead of giving every consumer the same setup
isn't Git's compressed transfer more efficient than asking for a bunch of files
packfiles bundle objects, and delta compression can represent similar versions using their differences [6]
that can save space. it also means bundling and compression are work the system has to do [6]
choosing a transfer format means choosing a balance between CPU, bytes, reuse, and request overhead
like pre-zipping a folder versus sending whatever exact files i ask for
that's a decent analogy. neither option wins automatically
for a made-up job fleet, if many workers need the same immutable object, a reusable object response might help
if requests become tiny and latency-heavy, batching may help instead. measure the actual request shape
so caching isn't a free performance multiplier
no. suppose an invented regional cache goes away and all its clients rush the origin
the origin can become overloaded. retries can add even more traffic while it's already struggling
Google's SRE guidance covers retry budgets and shedding load to avoid cascading failures [13]
i would've called direct fallback the resilient option
it can help at small scale. now imagine every caller doing it simultaneously
a failure plan needs a bound on the extra work sent upstream
ask what happens after a cold restart, a whole-region cache failure, and a burst of new revisions
and if the server goes down, offline Git starts looking pretty good again
yes. online-first source control creates a service dependency where local Git offers more independence
that's my reading of the tradeoff. you would need availability targets that match how people and jobs rely on it
don't count saved disk space without counting the new outage path
back to refs. i thought branches were just cheap pointers
they are. in Git, a branch ref names the tip commit of a line of work [4]
the pointer is small. agreeing on a shared pointer's next value is a different problem
separate creating a version from choosing which version a shared name should point to
give me a race
invented example: main points to A. worker 1 wants main to point to B, worker 2 wants it to point to C
if both blindly overwrite the value, one update can hide the other from that name
compare-and-swap says: set main to B only if it still points to A
then worker 2 has to notice that A isn't current anymore
exactly. Git's update-ref supports checking an expected old object ID before updating [9]
and a transactional database can atomically read, validate, and write shared state. Spanner documents those guarantees [10]
creating independent objects and resolving a shared-name race deserve different concurrency rules
so when someone says lock-free, i should ask which operation
always. ask what state is shared, which writes can conflict, and what the system does on conflict
a narrow fast path doesn't remove the need for coordination everywhere else
for a review tool, i'd also distinguish a stored revision, approved work, and work selected for release
this is the part where thousands of merges during a test run sounds terrifying
here's the problem with a made-up pair of changes
A changes a function to return cents. B adds a caller that assumes the returned number is dollars
they can touch different files, merge without a text conflict, and still break together
Git won't know what cents means
a text merge combines edits using their common ancestry. overlapping edits can produce explicit conflicts [5]
a clean text merge doesn't establish that the combined program behaves correctly
your tests, interfaces, and review have to catch the dollars/cents problem
so test A, test B, then merge both isn't enough
correct. GitHub's merge queue checks a candidate against the latest target branch and queued changes ahead of it [14]
that makes the tested combination closer to the combination that will land [14]
it still depends on what the tests cover, and it costs time to run them
could you just let more tests run in parallel
you can improve throughput, but the combinations still matter
imagine a candidate passes against revision R while the target branch has already moved beyond R
you need a policy: revalidate, queue carefully, accept some integration risk, or isolate changes differently
and Anthropic chose which one
they report investing in post-merge and pre-deploy testing instead of a globally locked merge queue [1]
post-merge makes me nervous. do you just accept a broken main
the distinction to keep is merge versus deploy. putting code in shared history and releasing it are separate decisions
my takeaway: that policy needs fast detection, reliable containment, and a release gate you can trust
it's a workload-specific risk choice. a source-control benchmark can't prove it's safe for your product
especially if the bug is in a money transfer instead of a flaky research job
exactly. i'd ask which failures can be rolled back, which have irreversible effects, and which need stricter checks
automation can repair code quickly and still fail to undo damage that already happened
that question belongs in the design before you relax an integration gate
what did they actually get for all this migration work
reported results: 200× smaller CPU/memory footprint than Git mirrors, about 100× faster checkouts, 25% CI CPU-capacity gain [1]
are those basically the same improvement measured three ways
they describe different denominators. source-control infrastructure, checkout latency, and CI capacity aren't interchangeable
imagine checkout gets much faster, but tests dominate runtime. the total CI gain can be much smaller
that's why i'd ask for end-to-end measurements alongside the impressive component benchmark
building your own Git still sounds like a ridiculous five-month project
seven engineers built Scion, Antique, and related systems, migrating in five months [1]
should i read that as agents can just do the whole platform now
they note internal token spending beyond what other businesses would want [1]
one team's outcome can't establish a general capability. engineers still have to choose guarantees and test edge cases
i'd want adversarial cases: missing objects, denied access, interrupted operations, retries, and concurrent changes
so should my small agent setup switch away from Git
Anthropic explicitly says Scion suits exceptional workloads and isn't a general Git replacement [1]
for your setup, i'd keep Git and start with the slowest repeated step you can actually measure
check whether each agent needs a new clone, whether objects can be reused safely, and how much history jobs need
and use an API when i just want changed paths rather than booting a whole workspace
yes, where the service offers the answer with the guarantees you need
try sparse or partial workflows when appropriate, and validate them against real tasks, including history-dependent commands
then measure the whole loop: preparation, editing, checks, review, landing, deployment, and recovery
ok. the article is easier to read now. i was stuck on why they'd give up local repos
the useful question is what each consumer needs to know and what work it repeats to learn it
keep that question in mind as you read the source. it'll connect the data model, caches, and CI decisions
got it. keeping Git for now. checking my agent setup costs tomorrow
sounds good. source links are below if you want to check any of the details
Read Wed, Oct 14 · 9:51 AM