What happens during a Crab push?
A visual walkthrough of the fourteen stages behind one safe Crab push.
A Crab push has one hard rule:
Upload first. Prove everything exists. Move the branch last.
The implementation has fourteen stages, but you only need four ideas to understand it: plan, upload, prove, publish.
PUSH CONTROL SHEET · CLICK ANY STAGE
Fourteen checks. One visible change.
KEY DATA STRUCTURE
PushSpecsrc01dst02force03STATE CHANGE
Parse refspec
Resolve the source and destination ref.
GUARANTEE ADDED
Intended ref edit
READERS SEE
main → A
Start with one real push
Imagine main points to commit A. Your local commit B changes two files:
src/train.rs 4 KiB source change
models/ranker.bin 12 GiB model updateThe new model shares about 80% of its chunks with the previous version. That percentage is illustrative; actual reuse depends on the file content.
git add src/train.rs models/ranker.bin
git commit -m "Improve ranking model"
crab push origin maincrab push uses Crab's native concurrent path. A normal git push to a crab:// remote enters the same publication model through Git's remote helper.
The intended result is simple:
main: A ───────────────► B
visible visible only after proofWhile the push runs, readers continue to see A. Uploaded bytes do not make B visible.
The fourteen stages fit into four phases
| Phase | Stages | Question Crab answers | Visible branch |
|---|---|---|---|
| Plan | 1–4 | What ref and objects does B need? | A |
| Upload | 5–10 | Are the Git and large-file objects durable? | A |
| Prove | 11–12 | Can another client reconstruct everything? | A |
| Publish | 13–14 | Is A still current, and may the ref move? | A, then B |
That last cell is the key. Stage 14 is the only visibility change.
Phase 1: plan the complete push
Stages 1–4 resolve the ref edit, read the destination tip, acquire the ref lock, and walk commit B.
The walk finds two kinds of dependencies:
- Git objects: commit, trees, source blobs, and Crab pointer blobs.
- Crab objects: file recipes, chunks, xorbs, and shards needed by each pointer.
For the example, the plan records A as the expected old value of main. If the model pointer has neither staged content nor proven remote metadata, the push stops here.
Phase 2: upload immutable objects
Stages 5–10 prepare both data lanes. Select a lane to isolate its work.
DUAL-LANE ROUTE MAP
Two object types arrive at one gate
Crab classifies the model chunks before uploading. With the illustrative 80% reuse:
| Model content | Approximate size | Push action |
|---|---|---|
| Already proven at the origin | 9.6 GiB | Reuse existing chunk locations |
| New content | 2.4 GiB | Pack into xorbs and upload |
| File mapping | Small metadata | Publish complete shard terms |
Crab can build and upload independent immutable objects concurrently. It still preserves the dependency order: staged xorbs flush before metadata can refer to them.
An interrupted upload may leave a complete but unreachable object. That is safe. No ref points to it, a retry can reuse it, and garbage collection can reclaim it after the grace period.
Phase 3: prove both closures
Stages 11–12 ask two different questions:
- Git closure: Can the origin reach every commit, tree, and blob required by
B? - Pointer closure: Can every Crab pointer resolve through durable shards to durable xorb bytes?
A local cache can make these checks faster, but it cannot supply the proof. The shared origin must contain the dependencies because another machine will not have the writer's cache.
For models/ranker.bin, pointer closure means the recipe covers every ordered chunk—including the reused 9.6 GiB and the new 2.4 GiB.
Phase 4: compare, then publish
Stage 13 reads main again and compares it with expected-old A.
- If
mainis stillA, stage 14 can commitA → B. - If another writer changed it to
C, Crab rejects this ref update.
The rejected push may have uploaded useful immutable data. It did not overwrite C. After reconciling the history, a retry can reuse objects that are already durable.
INCIDENT SELECTOR
Where did the push stop?
Object upload is interrupted
No closure proof, so the ref gate stays closed.
READERS SEE
A
unchanged
MAY BE DURABLE
Some complete immutable objects
NEXT MOVE
Retry and reuse completed uploads
The lock and expected-old check have different jobs:
| Mechanism | Job |
|---|---|
| Ref lock | Avoid duplicate contested work on the same destination |
| Expected-old comparison | Prevent a stale writer from replacing newer history |
Locks can expire. The expected-old check at the visibility boundary is what protects the ref decision.
What happens when a stage fails?
Use the incident selector above to move between an interrupted upload, a failed proof, two competing writers, and post-commit cleanup. The visible state is always a complete ref.
| Failure point | What may remain | What readers see | Next move |
|---|---|---|---|
| Discovery | Local staging | A | Fix the missing input |
| Object upload | Complete immutable objects | A | Retry and reuse them |
| Closure proof | Uploaded but incomplete dependency set | A | Restore the missing dependency |
| Expected-old check | All uploaded dependencies | Winning ref, such as C | Fetch, reconcile, retry |
| After ref commit | Complete published state | B | Finish cleanup; do not roll back |
Crab does not delete uploaded objects when a stale ref loses. Another writer may already reuse those objects. Repository garbage collection decides when unreachable data is safe to remove.
Source-only, model-only, and mixed pushes
The transaction shape stays the same even when one lane has little work.
| Commit type | Git lane | Crab lane | Publication |
|---|---|---|---|
| Source only | New Git pack data | No new chunks | One ref transaction |
| Model only | Commit, tree, pointer | Reused and/or new xorbs | One ref transaction |
| Mixed | Source blobs and pointer | Reused and/or new xorbs | One ref transaction |
One history never gets two meanings of “pushed.” Every successful case ends at the same ref boundary.
Verify from a reader's point of view
A successful command exit is useful. A fresh reader is stronger proof.
# In a second clone or an isolated cache
git pull --ff-only origin main
git rev-parse HEAD
git show HEAD:models/ranker.bin
crab hydrate models/ranker.bin
crab fsckCheck four things:
- The fetched object ID is the pushed commit.
- Git can read the pointer blob.
- Hydration reconstructs the expected file.
crab fsckreports a complete repository.
For a concurrency test, start two writers from A. One may publish. The other must receive a conflict instead of silently replacing the winner.
- 1Plan every Git and Crab dependency behind the proposed commit.
- 2Upload immutable Git packs, xorbs, and complete shard metadata.
- 3Prove Git connectivity and pointer closure from canonical storage.
- 4Compare expected-old state and commit exactly one ref transaction.
Next, see how local caches reduce the reads that prepare and verify these stages.
KNOWLEDGE PROOF
Check the decision, not your memory.
At what point does a prepared Crab push become visible to other readers?