fix(strategy): defer checkpoint push only on a truly empty remote · Entire
fix(strategy): defer checkpoint push only on a truly empty remote
a05a6a8→main·
?
Karthik Rameshkumar·3d ago·1 file·+27 added/-21 removed
The first cut deferred whenever the push target had no *non-metadata* branch, which broke checkpoint sync to a remote that already carries entire/checkpoints/v1 but no user branch (the alternates canary seeds exactly this to force a non-fast-forward rebase).
The default-branch hazard #1743 guards against only exists when our push would create the remote's first branch — i.e. a truly empty remote. Once any head exists there, including a checkpoint branch from an earlier push, deferring cannot prevent the default being set and only blocks legitimate syncs. Narrow the guard to fire solely for a target with no refs/heads/*.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
01KXFWG7JGFND3AS833FDTQSJFView transcript
[?
Fix Checkpoint Push on Empty RemoteClaude Code·Opus 4.8[1m]·4 steps](/content/gh/entireio/cli/session/b46b1cd5-a38d-49b5-9758-c373a036b37f#timeline-01KXFWG7JGFND3AS833FDTQSJF/index.html)
Changes
1
cmd/entire/cli/strategy
Mmanual_commit_push.go+27/-21
59 unmodified lines
60
61
62
63
63
64
65
66
92 unmodified lines
159
160
161
162
163
164
165
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
169
178
179
180
181
11 unmodified lines
193
194
195
187
196
197
198
199
6 unmodified lines
206
207
208
200
209
210
211
212
2 unmodified lines
215
216
217
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
221
222
223
224
230
231
232
233
59 unmodified lines
if ps.pushDisabled {
return nil
}
deferAutomaticCheckpointPush := protectFirstUserBranch && deferCheckpointPushUntilNormalBranch(ctx, ps)
deferAutomaticCheckpointPush := protectFirstUserBranch && deferCheckpointPushOnEmptyRemote(ctx, ps)
// git-refs primary: push the per-checkpoint refs recorded in the push queue
// instead of the single v1 branch. (A configured git-branch mirror's v1 ref
92 unmodified lines
return nil
}
// deferCheckpointPushUntilNormalBranch keeps Entire's metadata from becoming
// the first branch on a repository. Hosting providers such as GitHub can make
// the first branch their default, so a pre-push hook must not independently
// publish checkpoint metadata before the user's first normal branch lands.
// deferCheckpointPushOnEmptyRemote keeps Entire's metadata from becoming the
// first branch on a repository. Hosting providers such as GitHub make the first
// branch a repository's default, so a pre-push hook must not independently
// publish checkpoint metadata to a remote that has no branches yet: the user's
// own branch, pushed by the same git invocation right after this hook, must be
// the one to land first.
//
// The guard triggers only for a genuinely empty push target (no refs/heads/*).
// Once any branch exists there — including a checkpoint branch already present
// from an earlier push or a separate setup — our push can no longer be the one
// that establishes the default branch, so deferring would only block legitimate
// checkpoint syncs (e.g. a non-fast-forward v1 update) without preventing any
// harm.
//
// A separate checkpoint remote is intentionally exempt: it is a dedicated
// metadata store, rather than the repository the user is pushing to.
func deferCheckpointPushUntilNormalBranch(ctx context.Context, ps pushSettings) bool {
func deferCheckpointPushOnEmptyRemote(ctx context.Context, ps pushSettings) bool {
if ps.hasCheckpointURL() {
return false
}
11 unmodified lines
if err != nil {
// Fail closed for checkpoint publication: the user's git push continues
// normally, while a later push can publish the pending metadata once the
// remote is reachable and has a normal branch.
// remote is reachable and has a branch.
logging.Warn(ctx, "checkpoint push deferred: could not inspect remote branches",
slog.String("remote", ps.remote),
slog.String("error", err.Error()),
6 unmodified lines
if lsErr != nil {
// Fail closed for checkpoint publication: the user's git push continues
// normally, while a later push can publish the pending metadata once the
// remote is reachable and has a normal branch.
// remote is reachable and has a branch.
logging.Warn(ctx, "checkpoint push deferred: could not inspect remote branches",
slog.String("remote", ps.remote),
slog.String("target", target),
2 unmodified lines
return true
}
for _, line := range strings.Split(string(out), "\n") {
fields := strings.Fields(line)
if len(fields) != 2 {
continue
}
branch := strings.TrimPrefix(fields[1], "refs/heads/")
if branch != fields[1] && branch != paths.MetadataBranchName {
return false
}
// A truly empty target (no heads) is the only case our metadata push
// could make the repository's default branch. Any existing head means
// it is safe to publish now.
if strings.TrimSpace(string(out)) == "" {
logging.Info(ctx, "checkpoint push deferred until the remote has a branch",
slog.String("remote", ps.remote),
slog.String("target", target),
)
return true
}
}
logging.Info(ctx, "checkpoint push deferred until a normal remote branch exists",
slog.String("remote", ps.remote),
)
return true
return false
}
// prePushCheckpointRefs drains the per-checkpoint push queue and batch-pushes the