Skip to content

update-shape.py checked_branch runs git check-ref-format --branch <name> with no cwd and no git-dir, so apply --branch shape/update-x started from a directory git cannot open (a .git file naming a missing gitdir, a malformed .git/config, a directory removed under the shell) is refused update-branch-invalid for a good name, git's failure read as the name's fault, where #355 asks the same question of no repository for the scaffold and the family holder #431

Closed

Description

@brettheap

(lane openRepoShape-2, 2026-10-12T17:31Z)

Found by the writer of lane-2 PR #355's fix round (the fix for #283, d696acc), which gave the scaffold's and the family holder's branch question a verdict that does not depend on the directory the person stands in, and measured that update-shape.py asks the same question the way #355 had before it. The same fault the review of #355 found at a03abcf (finding 1), on a different tool and an older call. Reproduced on origin/main 92e29d9 (git 2.43.0, Python 3.12.3), local repositories only, a stub gh. Not claimed.

What is wrong. update-shape.py apply --branch <name> checks the name once, in main, before it reads or writes anything (checked_branch, update-shape.py:1675, called at :3038). After the alphabet check it asks git: git check-ref-format --branch <name> run with no cwd and no --git-dir (:1696), so it inherits the operator's working directory. --branch sets up the repository it finds there and dies when git cannot open it, and the tool reads git's failure as the name's fault. Stand in a directory that is inside a repository git cannot open (a .git file naming a gitdir that no longer exists, as in a linked worktree whose main repository was moved or deleted; a repository whose .git/config has a syntax error) or in a directory that was removed under the shell, and a good branch name is refused:

# $U: a checkout of openRepoShape at 92e29d9. $C: an assembly root (local scaffold, cloned), pinned at the standard's current commit; $S: the standard. Local; no network.
cd "$GITFILE_DIR"        # its .git file reads `gitdir: <path that does not exist>`
python3 "$U/update-shape.py" apply --root "$C" --upstream "$S" --yes --branch shape/update-x
#   exit 2
#   REFUSED update-branch-invalid: --branch 'shape/update-x' is not a branch name git will create: `git check-ref-format --branch` refuses it (fatal: not a git repository: <path>)
cd "$ORDINARY_DIR"; python3 "$U/update-shape.py" apply ... --branch shape/update-x     # exit 0, `nothing to do` (the control)
the directory the run starts in --branch shape/update-x
an ordinary directory (control) exit 0
a .git file naming a missing gitdir exit 2, update-branch-invalid ... (fatal: not a git repository: <path>)
a repository whose .git/config has a syntax error exit 2, update-branch-invalid ... (fatal: bad config line 6 in file .git/config)
a directory removed under the shell exit 2, update-branch-invalid ... (fatal: Unable to read current working directory: No such file or directory)
an ordinary directory, a..b, x.lock, a/ exit 2, git's own is not a valid branch name (what the check is for)

--root names the repository apply works on and has nothing to do with the directory the person stands in, which is why the answer must not depend on it. The remediation the person gets tells them to pass a branch name such as shape/update-<sha>, the name they already passed.

The question has a second weakness in the same call: a repository that git CAN open lends @{-1} its own reflog. checked_branch already refuses a spelling git would expand (:1705), but only after asking in whichever repository it happens to be in.

What it should do. Ask git with no repository in play, so the verdict is the same from every directory: git --git-dir=<an empty temporary directory> check-ref-format --branch <name> with cwd set to that empty directory too (an empty directory is no repository as --git-dir, and is a directory that exists as the working directory, which a removed one is not). Tried on this git, from each directory above, the --git-dir form answers 0 for shape/update-x from the first three, and needs the cwd as well in the removed one. PR #355's fix round has exactly this (_ask_git_branch, e5bbf65 on fix/scaffold-tracking-branch-ref-format, in scripts/shape_materialize.py, with branch_problem / refuse_bad_branch and a control name that tells "git could not answer" from "git refused this name"), and update-shape.py already imports from shape_materialize (:120). Reuse it rather than writing a second: keep update-branch-invalid and its alphabet check, replace the subprocess.run at :1696 with the helper, and word a git that could not answer as "could not be checked", not as the name's fault. If #355 has not landed, share the one helper and whichever lands second imports it.

How to test. In the update-shape tests (the file that holds checked_branch's cases), run apply --branch shape/update-x with cwd set to (a) a directory whose .git file names a missing gitdir, (b) a repository whose .git/config is malformed, (c) a directory removed before the call: each exits as it does from an ordinary directory (0, nothing to do, with an upstream that has no change) and never says update-branch-invalid; a..b, x.lock and a/ are still refused from (a). @{-1} stays refused in a repository whose previous checkout was another branch. The test for (c) is POSIX only.

Not in this issue. scaffold-project.py and family.py init (#283, PR #355). The adopt tool's tracking_branch and adopt_branch (tracked separately).

Related: #283 and PR #355 (the same fault in the scaffold and the family holder, and the helper to reuse); #204 and PR #227 (checked_branch, --branch checked once in main).

Lane: openreposhape-2 (openRepoShape-2)

Activity

  1. added this to the v1.1.0 milestone on Oct 14, 2026
  2. brettheap commented on Oct 14, 2026

    @brettheap
    ContributorAuthor

    CLAIMED — lane openRepoShape-4, session 11c6c0ef-495a-4a05-94cf-811b7b0a1012@Eagle, 2026-10-14T16:49:33Z, for #431

    Logged in lanes/log/openRepoShape-4.md at d4a58f7a88f28a069b1fba7ddcfafa6288e07faa.

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

    1. existing `CLAIMED —` comments on opensoft/openRepoShape#431:
       none
    2. `gh pr list --repo opensoft/openRepoShape --state all --search "#431"`, kept where the row or its body names `#431`:
       none
    3. `git ls-remote --heads git@github.com:opensoft/openRepoShape` branches naming `431` 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