Push git-refs checkpoints from pre-push via the discovery queue · Entire
Push git-refs checkpoints from pre-push via the discovery queue
7fa01ba→main·
Soph·2w ago·3 files·+231 added/-6 removed
When the configured primary is git-refs, PrePush drains the push-discovery queue and batch force-pushes those per-checkpoint refs (one git push, +ref:ref force refspecs — independent histories, no fetch+rebase recovery) instead of pushing the v1 branch. Default config (git-branch) is unchanged.
- partitionLocalRefs drops stale queue entries (refs deleted locally); surviving refs are removed from the queue only on a confirmed push, so a failed/transient push leaves them for the next pre-push and never blocks the user's git push. - Shared post-push shadow cleanup extracted to cleanupPushedShadowBranches.
A configured git-branch mirror's v1 ref is not pushed here yet (downgrade-safety mirror push is later), and OPF stays descoped for git-refs.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
7ca5586da108View transcript
Changes
3
cmd/entire/cli/strategy
Mmanual_commit_push.go+77/-6
Mpush_common.go+37
Arefs_push_test.go+117
42 unmodified lines
... (additional unmodified lines omitted for brevity)
// prePushCheckpointRefs drains the per-checkpoint push queue and batch force-pushes
// the recorded refs (git-refs primary). Transient push failures are logged and
// swallowed — like the v1 path, they must not block the user's git push — and the
// refs stay queued for the next pre-push. OPF is not applied (it is descoped for
// the git-refs store for now).
func (s *ManualCommitStrategy) prePushCheckpointRefs(ctx context.Context, ps pushSettings) error {
repo, err := OpenRepository(ctx)
if err != nil {
logging.Warn(ctx, "git-refs pre-push: open repo failed; skipping checkpoint push",
slog.String("error", err.Error()))
return nil
}
defer repo.Close()
queue, err := checkpoint.PushQueueForRepo(ctx, repo)
if err != nil {
logging.Warn(ctx, "git-refs pre-push: resolve push queue failed; skipping checkpoint push",
slog.String("error", err.Error()))
return nil
}
queued, err := queue.Drain()
if err != nil {
logging.Warn(ctx, "git-refs pre-push: drain push queue failed; skipping checkpoint push",
slog.String("error", err.Error()))
return nil
}
if len(queued) == 0 {
return nil
}
// Drop stale entries (refs no longer present locally) so they don't block
// the queue forever, then push what remains.
existing, stale := partitionLocalRefs(repo, queued)
if len(stale) > 0 {
if err := queue.Remove(stale); err != nil {
logging.Warn(ctx, "git-refs pre-push: prune stale queue entries failed",
slog.String("error", err.Error()))
}
}
if len(existing) == 0 {
return nil
}
pushCtx, pushSpan := perf.Start(ctx, "push_checkpoint_refs")
pushErr := batchForcePushRefs(pushCtx, ps.pushTarget(), existing)
pushSpan.End()
if pushErr != nil {
// Leave the refs queued; the next pre-push retries. Non-fatal so the
// user's push proceeds.
logging.Warn(ctx, "git-refs pre-push: batch push failed; refs left queued for retry",
slog.String("error", pushErr.Error()))
return nil
}
if err := queue.Remove(existing); err != nil {
logging.Warn(ctx, "git-refs pre-push: clear pushed refs from queue failed",
slog.String("error", err.Error()))
}
cleanupPushedShadowBranches(ctx)
return nil
}
// partitionLocalRefs splits refs into those that exist locally (pushable) and
// those that don't (stale queue entries).
func partitionLocalRefs(repo *git.Repository, refs []plumbing.ReferenceName) (existing, stale []plumbing.ReferenceName) {
for _, ref := range refs {
if _, err := repo.Reference(ref, false); err != nil {
stale = append(stale, ref)
continue
}
existing = append(existing, ref)
}
return existing, stale
}
// batchForcePushRefs pushes all of refs to target in a single git push. Each
// uses a force refspec (+ref:ref), matching how non-branch checkpoint refs are
// already pushed: per-checkpoint refs have independent histories with no
// remote-tracking shadow.
func batchForcePushRefs(ctx context.Context, target string, refs []plumbing.ReferenceName) error {
if len(refs) == 0 {
return nil
}
refSpecs := make([]string, 0, len(refs))
for _, ref := range refs {
refSpecs = append(refSpecs, "+"+ref.String()+":"+ref.String())
}
if _, err := remote.PushWithOptions(ctx, remote.PushOptions{Remote: target, RefSpecs: refSpecs}); err != nil {
return fmt.Errorf("batch push %d checkpoint refs: %w", len(refs), err)
}
return nil
}
// pushRefIfNeeded pushes a ref to the given target if it has unpushed changes.
// The target can be a remote name or a URL for direct push.