Plan trunk first in batched bootstrap to cut per-branch graph fetches

main

Commit

Soph4mo ago

Before: each branch's checkpoint planning fetched the full commit graph from the source independently. For a repo with 152 feature branches that all descend from main, that meant ~152 full-history commit-graph fetches and ~152 independent first-parent walks, each traversing the same shared history. On a linux-sized source this was ~40 s of wall time during planning alone, before any object bytes moved.

Now the trunk is identified up front via the source's HEAD symref, planned first, and its commit reachability is captured as a hash set. Each subsequent branch's graph fetch passes trunk's tip as a have so the source returns only the divergence, and the first-parent walk terminates when it enters trunk's ancestry instead of walking back to root.

Pieces:

  • gitproto: expose HEAD symref on RefService.HeadTarget. v1 reads it from the symref capability; v2 adds "symrefs" to ls-refs and a "ref-prefix HEAD" argument so HEAD is actually returned (otherwise ref-prefix refs/heads/ filters it out and HeadTarget stays empty). HEAD itself is consumed for the symref target and not surfaced in the ref slice, matching v1 behavior where symbolic refs are filtered downstream.
  • gitproto: FetchCommitGraph takes an optional []plumbing.Hash of haves, forwarded into the v2 fetch command. Nil/empty preserves prior behavior.
  • planner: add FirstParentChainStoppingAt that terminates the walk when a commit is in a caller-supplied stop set. FirstParentChain becomes a thin wrapper with nil stop set for existing callers.
  • bootstrap: orderTrunkFirst reorders DesiredRefs so the HEAD branch is planned first; collectCommitHashes extracts just the commit hash set (~8 B per commit, ~11 MB for linux) from trunk's graph store before it is GC'd. Subsequent branches plan with trunk's tip as a have and trunk's ancestry as a stop set. Emits one of three diagnostic log lines at planning time so operators can see whether the fast path fired: trunk selected, trunk unset (no HEAD advertised), or trunk unset (HEAD filtered by --branch/--map). Subsumed branches (tip in trunk's ancestry) emit a single-checkpoint batch today — the pack push for those is a follow-up optimization.

Empty-chain edge case: when stop-at subsumes the branch tip, FirstParentChainStoppingAt returns nil and planCheckpointsFromChain falls back to [tip] so the existing execute-phase logic still creates the target ref.

Falls back to the original per-branch behavior when HeadTarget is empty or when the trunk ref is filtered out of the desired set, so sources without symref advertisement and scoped runs (--branch, --map) are not regressed.

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com Entire-Checkpoint: 32bf11bd8793

Checkpoints

can you review the changes in this branch

Claude CodeOpus 4.6[1m]
View session
Checkpoint 1

question: so now we fixed if a branch is 100% included in the default branch (or another branch) but what if a branch is branched of the 10th commit (from HEAD) of main, how would the code handle this

Claude CodeOpus 4.6[1m]
View session
Checkpoint 1