strategy: don't treat shallow merge-base miss as disconnected metadata · Entire
strategy: don't treat shallow merge-base miss as disconnected metadata
eaada83
On a shallow checkpoint clone, git merge-base reports "no common ancestor" whenever the real ancestor lives below the shallow boundary — git has no objects there. The disconnection check trusted that exit code as proof of disconnection, so an ordinary diverged-but-behind metadata branch on a shallow clone was misread as disconnected. That triggered a full-history cherry-pick reconcile, which then blew MaxCommitTraversalDepth on a deep team branch and aborted both entire push and entire doctor ("commit chain exceeded 1000 commits without reaching root"), leaving doctor looping on a fix that could never succeed.
checkpoint/v1 clones are routinely shallow (resume/explain fetch the tip with --depth=1 via FetchMetadataTreeOnly and nothing deepens them again), so this hit a normal user who fell behind while out of office.
Fix:
- New metadataDisconnected() only trusts a merge-base miss as a genuine disconnection when the repo is NOT shallow; on a shallow clone the verdict is suppressed and the refs are reported connected. Routed through IsMetadataDisconnected (warn hot path + doctor detection) and ReconcileDisconnectedMetadataRef (push + doctor fix), so the warn path stays network-free and the doomed reconcile no longer fires.
entire doctornow deepens the metadata branch (--unshallow, best-effort, without advancing the local ref) before the check when the repo is shallow, so it can still detect and repair genuine disconnections on an accurate, fully-materialized history.- Export remote.IsShallowRepository so both packages share one check.
With the false positive gone, push rebases the local-only commits onto the remote tip normally and doctor reports OK instead of erroring. Genuine empty-orphan disconnections are still caught (by doctor after deepening, and on push the rebase cap still refuses to combine unrelated histories).
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
Changes
6
cmd/entire/cli
checkpoint/remote
Mgit.go+3/-3
Mgit_test.go+6/-6
Mdoctor.go+20/-1
Mgit_operations.go+41
strategy
Mmetadata_reconcile.go+43/-5
Mmetadata_reconcile_test.go+110
64 unmodified lines
// isShallowRepository returns true when the git repository at dir is shallow. // IsShallowRepository returns true when the git repository at dir is shallow. func isShallowRepository(ctx context.Context, dir string) bool {
Mcmd/entire/cli/checkpoint/remote/git.go+3/-3
// checkDisconnectedMetadata detects and optionally repairs disconnected // local/remote metadata branches (the "empty-orphan bug"). func checkDisconnectedMetadata(cmd *cobra.Command, force bool) error {
... // (Function Implementation)
}
// metadataDisconnected reports whether the local and remote metadata commits // share no common ancestor, accounting for shallow clones. func metadataDisconnected(ctx context.Context, repoPath, localHash, remoteHash string) (bool, error) {
... // (Function Implementation)
}
// TestMetadataDisconnected_ShallowSuppressesFalsePositive verifies that a // merge-base miss on a SHALLOW repo is not reported as a disconnection. func TestMetadataDisconnected_ShallowSuppressesFalsePositive(t *testing.T) {
... // (Test Implementation) }
// TestMetadataDisconnected_GenuineDisconnectionOnFullRepo verifies that on a // non-shallow repo a real merge-base miss (two unrelated roots) is still // reported as disconnected. func TestMetadataDisconnected_GenuineDisconnectionOnFullRepo(t *testing.T) {
... // (Test Implementation) }
// Other functions and implementations here.