Document bootstrap batching design · Entire
Document bootstrap batching design
Sessions
a2d74df554b4View transcript
Changes
1
docs
Abootstrap-batching.md+264
Bootstrap Batching Design
bootstrap currently streams one source pack into one target push. That is good for many initial syncs, but it is not enough for very large single-branch repositories where one initial pack is itself too large for comfortable target-side unpacking and indexing.
This note sketches a batching design for large bootstrap jobs.
Goal
Reduce per-push size and target-side receive-pack / index-pack pressure for very large initial syncs, while preserving the main benefit of bootstrap:
- no full local object materialization in
git-sync - direct source-to-target relay
- clear operator-visible progress and restart points
Non-Goals
V1 batching should not try to solve every large-migration problem.
Out of scope:
- non-empty target incremental relay batching
- prune/delete behavior
- tag retargeting
- fully optimal pack-size planning
- arbitrary graph partitioning
Why Per-Ref Batching Is Not Enough
Per-ref batching is easy:
- push
refs/heads/main - then
refs/heads/release - then tags
That helps when there are many refs and each ref is moderate in size.
It does not help for repositories where a single branch is enormous. Linux master is the motivating example: even a single branch bootstrap can be too large for one target-side unpack/index step.
Preferred Model
Use branch checkpoint batching with temporary refs.
High-level idea:
- Choose a sequence of ancestor checkpoints for a source branch.
- Push them oldest to newest into a temporary target ref.
- Once the final tip is present, create the real target ref.
- Delete the temporary ref at the end.
This gives:
- bounded per-push transfer size
- bounded target-side unpack/index work per batch
- restart points between batches
- no partially initialized real branch refs visible unless the run finishes
Command Shape
Possible CLI extension:
git-sync bootstrap \
--batch-max-pack-bytes 1073741824 \
<source-url> \
<target-url>
Possible related flags:
--batch-max-pack-bytes--batch-ref-prefix refs/gitsync/bootstrap/--keep-temp-refs-on-failure
The first version should only need --batch-max-pack-bytes.
Temporary Ref Strategy
For each target branch:
- real target ref:
refs/heads/main - temp bootstrap ref:
refs/gitsync/bootstrap/heads/main
Flow:
- Create/update only the temp ref during intermediate batches.
- After the final tip batch succeeds:
- create the real ref at the final tip
- delete the temp ref
This keeps the target repository in a cleaner state:
- before completion, the real branch is absent
- after completion, only the final branch remains
If failure happens mid-run:
- the temp ref records progress
- the real ref is still absent
Checkpoint Selection
The most practical first heuristic is first-parent checkpointing.
For a branch tip:
- Walk first-parent ancestry backward.
- Sample candidate checkpoint commits.
- Starting from the oldest candidate, estimate each batch by doing a source fetch against the previous checkpoint as
have. - Pick the largest checkpoint whose pack stays under
--batch-max-pack-bytes. - Repeat until the branch tip is reached.
This is only a heuristic:
- actual pack size depends on delta choices and object reuse
- merges and deep side histories can make batch sizes uneven
But it is much simpler than exact graph partitioning and good enough for a first implementation.
Batch Flow For One Branch
Given checkpoints:
C1C2C3tip
The flow is:
- Fetch source pack for
C1with nohave. - Push it to temp ref
refs/gitsync/bootstrap/heads/main. - Fetch source pack for
C2withhave=C1. - Push update of temp ref to
C2. - Fetch source pack for
C3withhave=C2. - Push update of temp ref to
C3. - Fetch source pack for
tipwithhave=C3. - Push update of temp ref to
tip. - Create real target ref
refs/heads/mainattip. - Delete temp ref.
The final ref creation can be:
- one separate tiny push with no pack
- or combined with the last batch if command ordering and push semantics stay clear
The first version should prefer the separate final ref creation because it is easier to reason about.
Tags
Tags should not be pushed during intermediate branch batches.
Recommended rule:
- branch batches first
- tag creation only after all referenced branch/object checkpoints complete
This avoids cases where a tag points at an object graph that is not yet fully present on target.
V1 batching should support:
- branch refs only
Tag batching can be added later.
Restart and Recovery
Batching is only worth doing if failures are restartable.
Minimum restart model:
- Detect existing temp refs on target.
- Resolve their current hashes.
- Resume from the latest completed checkpoint instead of starting from zero.
If --keep-temp-refs-on-failure is false, cleanup can still happen on clean failures, but default restartability is more valuable than aggressive cleanup.
Safety Model
V1 batching should remain strict.
Allow only:
- empty managed target refs
- branch-only bootstrap
- no force
- no prune
- no existing real target refs for the managed branches
Fail if:
- temp refs already exist but do not match expected checkpoint progression
- estimated batch sizing cannot find a checkpoint under the configured limit
- final ref cutover fails
Implementation Shape
Suggested pieces:
BootstrapBatchexecution path ininternal/syncer- checkpoint planner:
- first-parent ancestry walker
- batch-size estimator
- temp ref naming helpers
- resume detector for existing temp refs
- final cutover helper
The estimator should reuse the existing relay mechanics:
- source fetch with
have - streamed push to target
But it will need one new planning pass to probe likely batch sizes before actual execution.
Operator Output
Batching should be explicit in output.
Text output should include:
batching=true- per-branch checkpoint count
- current batch number
- temp ref names when verbose
JSON should include:
batchingbatch_countcompleted_batchestemp_refs
Practical Risks
- pack-size estimation may require extra source fetches before actual execution
- checkpoint search may be slow on very deep histories
- target-side unpack/index cost may still be high even after batching, just smaller
- temp refs add cleanup and restart complexity
This is still likely worthwhile for very large initial migrations because it changes a single huge risky operation into several bounded ones.
Recommended Phases
Phase A:
- batch branch-only bootstrap
- no tags
- temp refs required
- no resume
- manual cleanup if interrupted
Phase B:
- add resume from existing temp refs
- add better progress reporting
- add batch-size estimation metrics
Phase C:
- consider tag creation after successful branch completion
- consider whether per-ref or per-branch parallelism is worth it
Phase D:
- only then consider using similar checkpoint batching ideas for non-empty target incremental relay