Skip to content

family.py add: after #646's move back of a member's gitlink, a .gitmodules that a git mv made name the variant is not mended, a file or link in the way has no remedy that keeps the member, and the plain mv it prints orphans a live submodule checkout #761

Closed

Description

@brettheap

Goal: every command an add refusal prints for a member recorded in the wrong case can be typed as printed, in each state git can leave it in, and leaves the member registered, its .gitmodules section naming its row's path, and any live checkout openable.

Filed by lane openRepoShape-5, from #646's PR (#670, head a837a023: its checklist candidates (e), (g) and (h), "Left out", and RV670's N1 from lane 3), and from the checklist candidate of #681's PR (#747, "family.py's case-variant move remedy breaks a live submodule checkout"). The validator halves of (e) and (g) are in the sibling issue for validate-family.py; this one is scripts/family.py only.

Lands after: lane 5's #646 (PR #670, fix/646-add-member-variant-remedy), which adds the RESTORE remedy these lines are about, and #685 (family.py add, #574's spelling remedies: <new name>, a pulled Members/README, git mv --sparse), which edits the same function. Line numbers are at #670's head a837a023 where the code is new, and at main 66b230ed for MOVE and MOVE_BACK.

Lines

Verify: tests/test_family_add_member_variant.py (new in #670; 37 tests that type every printed line and then the gate), tests/test_family_members_case_variants.py and tests/test_family_add_refusals.py pass on Linux. One new case per line, typed as printed to the gate and then to the add that was refused: a git mv members/IRRS Members/IRRS holder (the gate exits 0, the section says members/IRRS, git submodule update --init succeeds); a file at the row's path; a file under it; a file at members; and a live checkout at the variant whose commits survive the printed step. No macOS or Windows run (CI is Linux only, #597): the folding disk is emulated by disk_as, as #670 does.

Overlaps. Open branches that edit scripts/family.py: fix/646-add-member-variant-remedy (#670, _spellings_refusal), fix/684-family-holder-states (70153862), fix/686-bump-reachability (7567e60e), fix/688-family-init-values (aa95b6b2), fix/689-next-push-refspec (fa513848), fix/692-raw-folder-paths (#731, ab55c29f) and fix/693-local-remote-dir (96ebe450); by the file lists none of the others edits _members_spellings or _spellings_refusal, but #684 lists the case-variant git mv remedy among its lines, so read its head before starting. fix/681-validate-family-remedies (#747) and fix/648-bootstrap-and-gate-order (#682) edit the validator, not this file. scripts/family.py is not a pinned shape copy, so no upstream-changed row follows.

Parent: #459.

Milestone: v1.1.1. Each state needs a hand rename of members/, a git mv of a member's mount, or a file where a member goes: a follow-up to #646, not a regression, and it blocks nothing in v1.1.0.

🤖 Generated with Claude Code

Activity

  1. added this to the v1.1.1 milestone on Oct 17, 2026
  2. brettheap commented on Oct 17, 2026

    @brettheap
    ContributorAuthor

    (lane openRepoShape-5, 2026-10-17T01:17:07Z) Three more lines for this issue, from rv685's review of #685's pull request (#767, head 215e8102). They are in the same function as (e), (g) and (h) (_members_spellings and the rename back, _renamed_with_git, scripts/family.py:2906-2993 at that head), and add prints the rename back for one state and the move back for the next, so one writer takes them with the lines above. This issue lands after #767 as well as #670. Line numbers are at 215e8102.

    • A member's gitlink staged for removal beside a staged git mv members Members (rv685's candidate 1; measured by rv685: its probe "staged, then Members/IRSS unstaged"). git mv rewrote every section to Members/<P>, and one member's addition under the new spelling was then unstaged (Members/IRSS), so its removal at members/IRSS stays staged. HEAD holds members/IRSS; the index holds neither spelling of it. _members_spellings never sees it: the HEAD pass (:3105-3109) skips a name that _spelled_target calls canonical, and _renamed_with_git asks nothing about a section whose entry is gone (its conditions, :2930-2993). The rename back is printed, typed it exits 0, and it renames only the entries the index holds, so that member's section stays at Members/IRSS. add then goes through and commits that .gitmodules, and the gate refuses (rv685's table: gates 2/2/1, add 0). This is (e)'s section left naming the variant, reached by the rename back. Direction: where a section of .gitmodules (the work tree's or HEAD's) gives <spelling>/<P> for a member the index no longer holds there, keep the move back's words and (e)'s section line, or say the member's removal is staged and must be committed or undone first. Prove it with rv685's state.
    • The rename back is withheld by a file under a third spelling that git mv would take (rv685's NIT 5; read from source, not run). _renamed_with_git returns None unless every entry under another spelling is under ONE spelling (len(spellings) != 1, :2952), so a file at MEMBERS/notes beside the renamed Members/<P> entries sends add back to the move back, whose text has (e)'s gap (the section left at Members/<P>). rv685: "stricter than git mv needs" and "outside the issue's states". On a disk that keeps the two spellings apart, git mv -- Members members.renaming and the second step do not touch MEMBERS/notes, which add then refuses as its own family-members-dir-variant, with its own remedy. Direction: decide whether the rename back is printed for the spelling that holds a member's gitlink and the third spelling is left to its own remedy, one line each, or the third spelling is named first. A folding disk, where all three are one directory, is the case that needs care (not run: this host is case-sensitive).
    • family.py: add refuses, before the member is read and on every disk, any path under another spelling of members/, in its index, in HEAD or on disk, and names a remedy per entry that never moves the members' checkouts (#362, #363, #364) #574's plain git mv is refused in a cone-mode sparse checkout when an entry is on disk with its skip-worktree bit cleared (rv685's candidate 2: "Not run through add"). add picks the plain git mv where the entry is on disk (_on_disk_as_named, :3095-3098) and git mv --sparse only where git ls-files -t says S (_skip_worktree, :2778-2785). An entry outside the cone that is on disk with the bit cleared is neither. Measured here with plain git 2.43.0 and a file entry (not a gitlink, not through add): git sparse-checkout init --cone, set other, the file recreated under Members/IRSS/, git update-index --no-skip-worktree on it, then git mv -- Members/IRSS/f Members/IRSS/g exits 1 with "paths ... exist outside of your sparse-checkout definition, so will not be updated in the index", and the hint "Use the --sparse option". rv685's 3-step probe in a real cone checkout gave the same rc 1. Direction: treat an entry the sparse definition excludes as RENAME_SPARSE's, whatever its bit says: ask git sparse-checkout list or try the git mv --dry-run, then print --sparse (git 2.38 or later, as family.py add: a members/ renamed with git mv is renamed back in two steps through a free name, after what the disk lacks under it is put back, and a printed --sparse says the git it needs, so no remedy fails as typed (#685) #767's text now says). Run it through add on a gitlink before the text says it.

    Lane: openreposhape-5 (openRepoShape-5)

  3. brettheap commented on Oct 17, 2026

    @brettheap
    ContributorAuthor

    CLAIMED — lane openRepoShape-5, session 50cede29-ab82-4ca3-9f67-d98e1a58c8d2@Eagle, 2026-10-17T10:26:59Z, for #761

    Logged in lanes/log/openRepoShape-5.md at 1b312a9a059374b6f86cdd2ece4c895786321653.

    The three reads (lane-collision-protocol Rule 1):

    1. existing `CLAIMED —` comments on opensoft/openRepoShape#761:
       none
    2. `gh pr list --repo opensoft/openRepoShape --state all --search "#761"`, kept where the row or its body names `#761`:
       none
    3. `git ls-remote --heads git@github.com:opensoft/openRepoShape` branches naming `761` as a whole token:
       none
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions