fix(worktree): deepen shallow clones so worktree cleanup can verify push state - #86912
Merged
Conversation
…ush state The installer clones with --depth 1, so every default install is shallow. In a shallow repo, an older worktree HEAD (a past snapshot of main) is disconnected from current origin/main by the shallow boundary, so 'git log HEAD --not --remotes' misreports thousands of already-public commits as unpushed. The fail-safe unpushed guard then preserves every aged 'hermes -w' worktree forever, and the git-cherry squash-merge escape hatch never rescues them (22k 'ahead' >> max_ahead=20). Real incident: 21 of 25 hermes-* worktrees stuck on one install. Fix at the root, one owner: - _deepen_shallow_repo(): one-time blobless unshallow (fetch --unshallow --filter=blob:none; plain --unshallow fallback) run from the background startup pruner thread before classification, so history verdicts become correct and the backlog self-clears on the next 'hermes -w' startup. Fail-soft offline: keep preserving. - _cleanup_worktree(): when the unpushed verdict comes from a shallow clone, say 'Shallow clone — cannot verify push state' instead of the misleading 'has unpushed commits' message. - Document the shallow caveat on _worktree_has_unpushed_commits (the primitive stays conservative on purpose). Tests: real shallow clone over file:// reproducing the disconnect shape, covering detection, deepen+verdict flip, pruner E2E reap, offline fail-soft preserve, full-clone noop, and genuine-unpushed-work survival. Sabotage-verified: the E2E test fails with the deepen call disabled.
Contributor
૮ >ﻌ< ა ci reviewran on ee51e70 — fix(worktree): deepen shallow clones so worktree cleanup can
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Worktrees created by
hermes -won a default install are never cleaned up: the installer's--depth 1shallow clone disconnects older worktree HEADs from currentorigin/main, sogit log HEAD --not --remotesmisreports thousands of already-public commits as "unpushed" and the fail-safe guard preserves every aged worktree forever. This PR makes the startup pruner deepen the clone once (bloblessly), after which the verdicts are correct and the accumulated backlog self-clears on the nexthermes -wstartup.Real incident: 21 of 25
hermes-*worktrees stuck on one install, each kept with a misleading "has unpushed commits" message at session close. Thegit cherrysquash-merge escape hatch can't rescue them either — a shallow-disconnected tree reports ~22k commits "ahead", far pastmax_ahead=20.Changes
cli.py: new_repo_is_shallow()+_deepen_shallow_repo()— one-timegit fetch --unshallow --filter=blob:none(plain--unshallowfallback), invoked from the background startup pruner thread before classification. Fail-soft: offline/no-remote keeps today's preserve-everything behavior.cli.py_cleanup_worktree(): when the unpushed verdict comes from a shallow clone, print "Shallow clone — cannot verify push state" (with a pointer to the auto-deepen) instead of the false "has unpushed commits".cli.py_worktree_has_unpushed_commits(): documents the shallow caveat; the primitive intentionally stays conservative.tests/cli/test_worktree.py:TestShallowCloneDeepening— real shallow clone overfile://reproducing the disconnect shape.Validation
Infographic
Omitted this once with maintainer approval — FAL image generation unavailable (billing balance exhausted at PR time).