git-refs pre-push: show push progress instead of a silent stall · Entire
git-refs pre-push: show push progress instead of a silent stall
a4b3f75→main·
Soph·1w ago·1 file·+14 added/-0 removed
The git-refs pre-push path pushed the queued checkpoint refs via batchPushRefs
with no output, so pushing a large backlog (e.g. a freshly migrated repo) looked
like git had hung for 30+ seconds while git push reported only "Everything up
to date" for the branch.
Mirror the v1-branch path's progress line: print "[entire] Pushing N checkpoint
ref(s) to
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
f55c74d61bafView transcript
Changes
1
cmd/entire/cli/strategy
Mmanual_commit_push.go+14
2 unmodified lines
3
4
5
6
7
8
9
181 unmodified lines
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
1 unmodified line
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
3 unmodified lines
228
229
230
231
232
233
234
2 unmodified lines
import (
"context"
"errors"
"fmt"
"io"
"log/slog"
"os"
181 unmodified lines
pushCtx, pushSpan := perf.Start(ctx, "push_checkpoint_refs")
defer pushSpan.End()
// Progress: pushing many refs over the network can take tens of seconds, so
// surface it (matching the v1 path's "[entire] Pushing ..." line) instead of
// leaving the user's git push apparently hung. Written to stderr, which git
// shows during the pre-push hook.
displayTarget := displayPushTarget(ps.pushTarget())
fmt.Fprintf(os.Stderr, "[entire] Pushing %d checkpoint ref(s) to %s...", len(existing), displayTarget)
stop := startProgressDots(os.Stderr)
// Fast path: push all refs in one round-trip (fast-forward-only). If every
// ref was up to date or fast-forwarded, we're done.
if err := batchPushRefs(pushCtx, ps.pushTarget(), existing); err == nil {
stop(" done")
if removeErr := queue.Remove(existing); removeErr != nil {
logging.Warn(ctx, "git-refs pre-push: clear pushed refs from queue failed",
slog.String("error", removeErr.Error()))
}
cleanupPushedShadowBranches(ctx)
return nil
}
stop("")
// At least one ref was rejected — typically a non-fast-forward divergence
// (the same checkpoint re-written on another machine). Retry per ref with
// fetch+replay recovery, and remove from the queue only the refs that land
// (a genuine cherry-pick conflict leaves that ref queued for a later push,
// never force-overwriting the remote).
fmt.Fprintf(os.Stderr, "[entire] Some checkpoint refs diverged; syncing %d ref(s) individually...", len(existing))
stop = startProgressDots(os.Stderr)
pushed := make([]plumbing.ReferenceName, 0, len(existing))
for _, ref := range existing {
if err := pushCheckpointRefWithRecovery(pushCtx, ps.pushTarget(), ref); err != nil {
}
pushed = append(pushed, ref)
}
stop(fmt.Sprintf(" pushed %d of %d", len(pushed), len(existing)))
if err := queue.Remove(pushed); err != nil {
logging.Warn(ctx, "git-refs pre-push: clear pushed refs from queue failed",
slog.String("error", err.Error()))
}
Mcmd/entire/cli/strategy/manual_commit_push.go+14