fix(issue-21): review ec50fbe7 R6 - the unpushed check covers HEAD and every local ref (tags included, stash excluded) in both submodule checks
Both unpushed checks in lib_py/worktree.py - `submodule foreach` over the initialised checkouts and the direct `--git-dir` walk over the repositories under the worktree's modules/ - used `HEAD --branches --not --remotes`. A commit made on a submodule's detached HEAD and kept only by a tag is reachable from neither, the top-level status stays clean, and worktree_remove.sh then deleted the repository with its single --force (exit 0). Both checks now share one rev list, UNPUSHED_REVS = HEAD --exclude=refs/stash --all --not --remotes: HEAD and every local ref (branches, tags, notes, ...) minus remote-tracking refs. refs/stash stays out of it because the stash check (stash list / reflog) owns it, so a stash is reported once, as 'stashes'. As intended, a local-only note is now protected too. The stash, error, partial repository and dirty checks are unchanged. Tests W6l (tag-only commit; initialised submodule and deinit'd repository) and W6m (annotated tag). The helper header, the stop SKILL.md and the design doc state the wider rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017R3Eg7MEpSWnm1oB9ZPP6G
This commit is contained in:
1 parent
c7c559b7aa
commit
25f4be3359
5 files changed
+59
-10
No files matched your search
@@ -121,7 +121,7 @@ Every check runs first and changes nothing; a refusal exits 3:
|
||||
2. running sessions under it only with `--stop` (stopped normally, conversations kept);
|
||||
3. no open job of those sessions - never cancelled automatically, they may belong to a running loop (the delegate job of a session `--stop` stops is cancelled by stop itself);
|
||||
4. a clean tree, submodules included (`status --porcelain --ignore-submodules=none`);
|
||||
5. inside submodules: no modification, no commit that is on no remote (`HEAD` included - a submodule sits on a detached HEAD) and no stash (`refs/stash` is reachable from no branch and leaves the status clean) - checked in every repository under the worktree's `modules/`, including deinitialised submodules (their repository stays there) and nested ones; a repository that cannot be checked refuses.
|
||||
5. inside submodules: no modification, no commit reachable from `HEAD` or any local ref that is on no remote (a submodule sits on a detached HEAD; a commit kept only by a tag or a note is protected too) and no stash (`refs/stash` is reachable from no branch and leaves the status clean) - checked in every repository under the worktree's `modules/`, including deinitialised submodules (their repository stays there) and nested ones; a repository that cannot be checked refuses.
|
||||
|
||||
Then it stops the sessions, re-checks the jobs, runs checks 4 and 5 **again** (a session that is being stopped can still write, commit or stash - any change refuses with exit 3, sessions already stopped) and removes the worktree (the branch is kept): plain, or - when the worktree holds submodule state, which git refuses to remove otherwise - a **single `--force` justified by checks 4 and 5**. Do not run `git worktree remove --force` by hand on such a worktree: it deletes the worktree's own submodule repositories, unpushed commits included.
|
||||
|
||||
|
||||
Reference in new issue
Block a user