Repository navigation
test_family_bump_fetch_refspecs.py: the comment on WHICH_CLAUSE and the docstring of test_which_clause_leaves_each_refspec_out say the source refs/h takes the one ref git completes it to, which may be a branch or tag, not no branch (#1230) - #1235
Conversation
… the docstring of `test_which_clause_leaves_each_refspec_out` say the source `refs/h` takes the one ref git completes it to, which may be a branch or tag, not `no branch` (#1230) The two passages said the carried refspec `+refs/h:refs/remotes/origin/hy` takes "the one ref of that name, which is no branch". That is true of an exact `refs/h` only. Git completes the source `refs/h` to the exact ref, to the branch `refs/heads/refs/h` or to the tag `refs/tags/refs/h`, so a remote that holds a branch or a tag of that name has a source that is one, and beside a branch `hy` the fetch exits 128 `Cannot fetch both refs/heads/hy and refs/heads/refs/h to refs/remotes/origin/hy` (measured in #1230, git 2.43.0 and 2.47.1). The clash is the one any carried refspec has where its destination is a branch's name, so the passages now say that instead of "no branch". Wording only, in a comment and a docstring. The row `carried-refs-h-not-a-pattern`, the file's syntax tree outside that docstring and the scripts are as on main. (The re-check of #1157, NIT 1.) Closes #1230 Lane: openreposhape-5 (openRepoShape-5) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reviewer's guide (collapsed on small PRs)Reviewer's GuideThis wording-only PR updates one comment and one test docstring so they accurately describe Git’s ref completion and destination collision behavior for the carried File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Independent review of #1235 (#1230) for lane openRepoShape-5, by rv1235 (sonnet), at 644982d: READY I found no MUST. Two SHOULDs show that the new wording is still not true of git in two places. I recommend folding both in before the PR leaves draft. Each is a one-sentence rewording, and the syntax-tree check can then be re-run. What I checked and measuredSetup: disk had 13G free at the start and 30G at the end. My worktree is 1. Probes of git behaviour. Local bare remotes,
The four cases in the PR body's table hold on both gits. "The one ref" also holds. When several exist, git takes one:
Two other probes, 2. The issue's Verify items.
All runs went through 3. The PR body's claims.
4. Other sentences saying the source
FindingsSHOULD 1: "like any carried source" is false of a carried branch. The docstring (lines 693-694) says
SHOULD 2: the list "
NIT 3: wording.
NIT 4: the PR body says
NIT 5: the live PR body ends with a Sourcery section. Lane: openreposhape-5 (openRepoShape-5) |
… the docstring of `test_which_clause_leaves_each_refspec_out` name the refs git completes `refs/h` to, and say a pull request's fetch clashes, not any carried one's (#1235) The independent review of #1235 (issuecomment-6375269462, READY, two SHOULDs) found the first round's wording still untrue of git in two places. The docstring said `refs/h` clashes "like any carried source". A carried branch does not clash onto its own name: `+refs/heads/main:refs/remotes/origin/main` exits 0 where `+refs/pull/7/head:refs/remotes/origin/main` exits 128. It now says the fetch clashes as a pull request's ref does. Both passages listed what git completes `refs/h` to as "the branch or tag of that name", a list that reads as closed. Git also completes it to `refs/refs/h` and `refs/remotes/refs/h`. Both now say the ref is `refs/h` itself or a ref git completes it to, such as the branch `refs/heads/refs/h` or the tag `refs/tags/refs/h`, and the citation follows the clause in parentheses. Wording only, in a comment and a docstring. The file's syntax tree outside that docstring is as on main. The docstring in `scripts/shape_materialize.py` that says "ANY OTHER SOURCE NAMES NO BRANCH" is left for a follow-up issue. Lane: openreposhape-5 (openRepoShape-5) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
Re-check of #1235 (#1230) for lane openRepoShape-5, by rv1235 (sonnet), at 8158230: READY I found no MUST and no SHOULD. SHOULD 1, SHOULD 2, NIT 3 and NIT 4 of my first review are fixed, and I found three small NITs.
What I checked and measuredMy worktree (1) The new sentences, against my earlier probes.
(2) The gates at the new head. All through
(3) The live body and #1238.
FindingsNIT 1: one literal edge remains in the docstring. "Whose fetch clashes ... where its destination is a branch's name" is not true of NIT 2: #1238's text has two small gaps.
NIT 3: the live body.
Lane: openreposhape-5 (openRepoShape-5) |
Main moved past #1180's squash 4829418 by e9a1650 (#1109) and bd3e9c1 (#1235), which touch shape-doctor.py, tests/test_doctor_plan_overrides.py, tests/test_family_bump_fetch_refspecs.py and tests/test_path_guard_hygiene.py. None of them is a file #1190 changes. This is the third of the three merges that restack #1190 after #1180 landed. Lane: openreposhape-1 (openRepoShape-1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…says a full name that is no pattern takes the one ref git completes it to, which may be a branch, where it said any other source names no branch (#1238) (#1244) #1238 is a wording NIT that the review of #1235 (#1230) found in the code: NIT 4 of rv1235's first review, and NIT 2 of its re-check. The docstring of `gives_a_branch_another_name` in `scripts/shape_materialize.py` ended "ANY OTHER SOURCE NAMES NO BRANCH", but git completes a source that is a full name and no pattern, and completes `refs/h` to the branch `refs/heads/refs/h` where the remote has one. The sentence now says what git does with such a source, as an open list ("such as"), and where the clash is. A reader of the docstring is no longer told that a source outside `refs/heads/` is never a branch. Wording only, in one docstring of one file: 9 lines added, 3 removed. No code, no row, no other file. The file's syntax tree with every docstring dropped is the same as main's. The sentence is at `scripts/shape_materialize.py:1720-1723`, the end of the docstring of `gives_a_branch_another_name` (line 1671): ``` 1720: BRANCH REACHES). A shorter start, such as `refs/*` or `*`, can name a 1721: tag, and that clause has left it out first. ANY OTHER SOURCE NAMES NO 1722: BRANCH, though a refspec from one can still put a ref on a branch's 1723: name: `origin_fetch_refspecs` says where (WHAT CAN STILL CLASH). ``` It is true of a source in another namespace such as `refs/pull/7/head`. It is not true of every other source. A source that is a full name and no pattern takes the one ref git completes the name to on the remote: for `refs/h`, `refs/h` itself, the branch `refs/heads/refs/h`, the tag `refs/tags/refs/h`, `refs/refs/h` or `refs/remotes/refs/h`, and where several exist git takes the exact ref over a tag over a branch. Where the remote has the branch, the source is a branch. The code is right: `gives_a_branch_another_name("refs/h", ...)` is False, because the source has no `*` and does not start with `refs/heads/`, so the refspec is carried. What fails afterwards is the clash the docstring's own next clause names. Only the words were untrue. Measured on this branch's base, with git 2.43.0 (`/usr/bin/git`) and git 2.47.1, which gave the same answers on every row. Local bare remotes, `GIT_CONFIG_GLOBAL=/dev/null`, `GIT_CONFIG_NOSYSTEM=1`, `GIT_SSH_COMMAND=false`. rv1235's probe scripts were run again here (copied unchanged, new output folders), and their logs are identical to rv1235's. The fetch was `+refs/heads/*:refs/remotes/origin/*` plus the refspec of the row, and the remote had `main` and `hy`: ``` the remote has refspec result branch refs/heads/refs/h +refs/h:refs/remotes/origin/hy 128 Cannot fetch both refs/heads/hy and refs/heads/refs/h to refs/remotes/origin/hy tag refs/tags/refs/h +refs/h:refs/remotes/origin/hy 128 Cannot fetch both refs/heads/hy and refs/tags/refs/h to refs/remotes/origin/hy exact ref refs/h (update-ref) +refs/h:refs/remotes/origin/hy 128 Cannot fetch both refs/heads/hy and refs/h to refs/remotes/origin/hy refs/refs/h or refs/remotes/refs/h +refs/h:refs/remotes/origin/hy 128, the same message naming that ref each of those five refs, alone onto origin/not-a-branch 0, holds that ref's commit branch refs/heads/refs/h onto origin/refs/h 0 (the branch's own name: no clash) refs/pull/7/head onto origin/main 128 Cannot fetch both refs/heads/main and refs/pull/7/head to refs/remotes/origin/main branch refs/heads/main onto origin/main 0 ``` So a name with no `*` can be a branch that its spelling does not show, and the clash is a ref that is not that branch put on a branch's name, which is what the second half of the sentence has to say. "ANY OTHER" was wrong in a second way: a carried refspec from a source that IS the branch does not clash onto that branch's own name. The docstring's last sentence, now lines 1721-1729: ``` tag, and that clause has left it out first. ANY OTHER SOURCE TAKES NO BRANCH BY A PATTERN, and a full name that is no pattern, such as `refs/h`, takes the one ref git completes it to on the remote: that ref itself, or one such as the branch `refs/heads/refs/h` or the tag `refs/tags/refs/h` (measured, git 2.43 and 2.47.1). Such a name can stand for a branch its spelling does not show, so it is not left out here. A refspec from any such source can still put a ref on a branch's name, if the ref is not that branch itself: `origin_fetch_refspecs` says where (WHAT CAN STILL CLASH). ``` - **"Takes no branch by a pattern"** holds for every source this sentence covers. Git matches a pattern against each ref's whole name, and a ref under `refs/heads/` starts with the part before the `*` only where that part is a start of `refs/heads/` or is under it, the two cases the function reads before this sentence. - **The list is open** ("one such as"): it names the exact ref, the branch and the tag, and the rows above show two more completions (`refs/refs/h`, `refs/remotes/refs/h`), so no reader takes the three as all. - **"So it is not left out here"** is what the code does: `gives_a_branch_another_name` is False for `refs/h` onto `origin/hy`, onto `origin/refs/h`, for `refs/pull/7/head` onto `origin/main`, and for the pattern `refs/pull/*/head`, and `origin_fetch_refspecs(["+refs/h:refs/remotes/origin/hy"])` returns it carried. It is True for `refs/heads/main` onto `origin/hy`, as before. - **"If the ref is not that branch itself"** is the condition the rows show: the clash is two different refs on one name, a branch's. The checks the issue's Verify lists: - **The diff is only that docstring.** The diff has one hunk, inside the docstring, which spans lines 1672-1724 on main and 1672-1730 here. The file's tree with every docstring dropped (module, class and function: 168 each side) is equal on main (`50869f384`) and at this head under `python3 -I`, `ast.dump`: 380120 characters of dump on both sides. A control that renames `gives_a_branch_another_name` on the head side gives 380121 and DIFFERENT, and the same trees with the docstrings kept differ (520956 against 521366), so the check can fail. Python 3.12.3. The check compares two dumps made by one interpreter and asserts no text that depends on the version. - **`git grep -n 'ANY OTHER SOURCE NAMES NO$' -- scripts/`** finds nothing at this head. On main it finds `shape_materialize.py:1721`. With any case and no line end, `git grep -n -i 'other source names no'` also finds nothing here, and nothing but that line on main. - **No added line is over 79 columns or holds a non-ASCII character.** 9 lines are added, the longest is 75 columns, and none has a tab or trailing space. The file's own width is unchanged: 20 lines over 79 columns (longest 118) and 90 lines with a non-ASCII character, as on main, none of them mine. - **No test, `README.md`, `docs/` page or `AGENTS.md` line pins the sentence.** The issue's grep holds at this head. The issue asks whether `shape_materialize.py:1874` (now 1880, in the docstring of `origin_fetch_refspecs`) and `bump-leg.py:1165` (in `_leg_fetch_refspecs`) want the same change. Both paragraphs were read, and both are left as they are: ``` shape_materialize.py:1880: WHAT CAN STILL CLASH is a refspec carried whose source names no branch, bump-leg.py:1165: whose source names no branch, onto a name a branch of the remote has ``` 1. **They define a shape by its examples and say nothing about what git completes a name to.** Each goes on at once to the pull requests (`origin/pr/` where a branch `pr/7` is, and `+refs/pull/7/head:refs/remotes/origin/main` beside a branch `main`), and neither names `refs/h`. They were not the sentence that told a reader a source is never a branch. 2. **"Names no branch" is spelling there, as it is in the sentence the function's docstring opens with.** "A SOURCE UNDER `refs/heads/` NAMES BRANCHES" is true by spelling too: `can_name_a_tag`'s docstring measures that `+refs/heads/zz` took the tag `refs/tags/refs/heads/zz` where the remote had no branch `zz`. The sentence changed here now says outright that the spelling of a name with no `*` does not show what it stands for, so the docstring that defines the class carries the caveat the two borrowers need. 3. **The mechanism they state is the one that fails `refs/h`:** "wherever a name it writes is a branch's". The `origin_fetch_refspecs` paragraph ends with why such a refspec is carried at all: "Which names the remote's branches have is not known from its refspecs, and left out, what such a refspec keeps would be pruned on every run". That holds for `refs/h` word for word. 4. **The cost of leaving them is one reading:** a reader who takes "names no branch" in git's sense meets the single case `refs/h` beside a remote branch `refs/heads/refs/h`. If the review wants a word there, it is a few words in each place, and no open PR touches either paragraph (merge-trees below), so it can be a fix round. None of either. No row is added or changed and no behaviour moved: the syntax tree outside the docstring is main's, so there is nothing for main to fail and nothing to mutate. `gives_a_branch_another_name` returns what it returned for every case in the table above (called in process at this head; the syntax tree outside the docstrings is main's). All through the lane's runner `run9.sh` (stub `gh` first on PATH, `GIT_SSH_COMMAND=false`, `GIT_CONFIG_GLOBAL=/dev/null`), on the committed head `36ec589a6` with the tree clean (`dirty=0`), as one run of seven files at a time: `tests/test_pinned_copy_text.py`, `tests/test_path_guard_hygiene.py`, `tests/test_repo_hygiene.py`, `tests/test_agents_md_codes.py`, `tests/test_cli_reference.py` (the hygiene five), `tests/test_family_bump_fetch_refspecs.py` and `tests/test_bump_leg_fetch_refspecs.py`. - **The seven files, git 2.43.0** (`/usr/bin/git`): 504 passed in 469.44s (47 `test_agents_md_codes.py`, 68 `test_bump_leg_fetch_refspecs.py`, 23 `test_cli_reference.py`, 57 `test_family_bump_fetch_refspecs.py`, 121 `test_path_guard_hygiene.py`, 87 `test_pinned_copy_text.py`, 101 `test_repo_hygiene.py`; the counts are from `--collect-only -q` on the same head and add up to 504). Log `v131/n1238/gate-g243.log`. - **The seven files, git 2.47.1** (first on PATH, `git --version` printed into the log): 504 passed in 714.00s. Log `v131/n1238/gate-g247.log`. - **`-k carried-refs-h-not-a-pattern`** over `tests/test_family_bump_fetch_refspecs.py` and `tests/test_bump_leg_fetch_refspecs.py`: 2 passed, 123 deselected, on 2.43.0 and on 2.47.1 (`run-k-g243.log`, `run-k-g247.log`). - Both runs start with `dirty=0`. Python 3.12.3 (CI runs 3.14); nothing asserts text that depends on the version. The measured git behaviour above comes from the probe scripts, not the test files. `-k carried-refs-h-not-a-pattern` over the two fetch-refspec files is part of those runs. `git merge-tree --write-tree origin/main HEAD` exits 0, with tree `9d874bcf2caf`, equal to this head's tree, against main `50869f384` (the merge base). Against the head of each open PR that touches `scripts/shape_materialize.py` or `scripts/bump-leg.py` (read from `gh pr list --state open --limit 100 --json number,headRefName,headRefOid,files`, 52 open PRs at the last read, 7 of them touch one of the two files), `git merge-tree --write-tree HEAD <head>` exits 0 and the merged tree still holds the new sentence and not the old one: ``` #1223 f50b472 exit 0 #1207 6fa1edd exit 0 #1160 0068f5a exit 0 #1131 55c30f2 exit 0 #1118 2307036 exit 0 #1105 b28f40d exit 0 #1104 de89aa8 exit 0 ``` Main moved once while this was gated, to `4829418f0` (`adopt-project.py`, `docs/cli.md` and a new test file: none of the files this change or its runs touch), and `git merge-tree --write-tree origin/main HEAD` against it also exits 0. None of their hunks is within 100 lines of the sentence changed here. Review: rv1244 and rv1244b, lane 5's independent sonnet reviewers, which wrote none of #1244: READY at `36ec589a6`, H0 of this landing (issuecomment-6723280477), with no MUST or SHOULD; its four NITs are optional (two wordings, a body note and a follow-up). CI (Brett Heap's ruling 27): H0 is the head 473959f itself, which passed tests, tests-git-bash and SonarCloud; main has touched none of its files since its base 9729315; and the local gate passed on its predicted squash tree fb798f3 over main 9252ef2: the repo_hygiene, agents_md_codes, cli_reference sets, 171 passed. Landed on Brett Heap's word of 2026-10-23T13:10:26Z, relayed to every lane by lane 3 (#473 issuecomment-6365697123): "merge v1.2.1 PRs once reviewed and green". Closes #1238 Lane: openreposhape-5 (openRepoShape-5) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>



Goal
#1230 is a wording NIT left by the re-check of #1157 (#1100, NIT 1). Two passages of
tests/test_family_bump_fetch_refspecs.pysaid that the carried refspec+refs/h:refs/remotes/origin/hytakes "the one ref of that name, which is no branch". They now say what git does with the sourcerefs/h: it takes the one ref that name stands for, which isrefs/hitself or a ref git completes it to, such as the branchrefs/heads/refs/hor the tagrefs/tags/refs/h. A reader of thecarriedrule is no longer told that the source is never a branch.Wording only, in one comment and one docstring of that file. No row, no script, no other file. Two commits: the first (
644982da1) is the wording, and round 1 (81582301e) answers the independent review rv1235 (#1235 issuecomment-6375269462: READY, no MUST, two SHOULDs, three NITs). See "Round 1" below.What held on main (
e04826db4)The file's blob on main is
6e752bbca9c9, the same as at #1157's head, and it is still that blob on main0ed3e57f8. The two passages are at the lines the issue names:That is true of an exact
refs/honly. A remote can also hold a branchrefs/heads/refs/hor a tagrefs/tags/refs/h, and git completes the sourcerefs/hto either. Measured on this branch's base, with a local bare remote per row (no network,GIT_CONFIG_GLOBAL=/dev/null,GIT_CONFIG_NOSYSTEM=1), the remote holdingmainandhyfrom one empty commit and then the ref of the row, and a fresh mount with that remote asoriginrunninggit 2.43.0 and git 2.47.1 gave the same answers:
So the source can be a branch or a tag, and what clashes is the destination: the first three rows fail because
origin/hyis where the glob puts the branchhy, and the same sources fetch with exit 0 onto a name no branch has. The fourth row is the other documented way a carried refspec fails, a source the remote lacks, and is not this clash.The review (rv1235) measured two more completions on both gits:
refs/refs/handrefs/remotes/refs/hare taken too (exit 0 onto a free name, and 128Cannot fetch both refs/heads/hy and refs/refs/hand... refs/remotes/refs/h ...ontoorigin/hy), so the list of what git completes the name to is open. It also measured a carried branch:+refs/heads/main:refs/remotes/origin/mainand+refs/heads/rel/*:refs/remotes/origin/rel/*exit 0, where+refs/pull/7/head:refs/remotes/origin/mainexits 128Cannot fetch both refs/heads/main and refs/pull/7/head. So a carried source clashes onto a branch's name when it is not that branch.What changed
Both passages say the same thing, in this file only. The comment above
WHICH_CLAUSE, lines 580-586 (reflowed to the end of its sentence):The docstring of
test_which_clause_leaves_each_refspec_out, lines 692-697:tests/test_family_bump_fetch_refspecs.py, all in that comment and that docstring.git diff --checkis clean.0d76e4c59and shape_materialize.py and bump-leg.py: the fetch for a branch's answer leaves out a pattern likerefs/heads*that puts a branch under another name, its clauses move into_left_out, and the docstrings name the clashes left and the way back (#1100) #1157's body carry the old sentence and cannot be changed. These two passages are the only place to correct it.scripts/bump-leg.py(1165) andscripts/shape_materialize.py(1874) define the clashing shape by examples and make no claim aboutrefs/h. The docstring ofgives_a_branch_another_name(scripts/shape_materialize.py:1721-1722) says "ANY OTHER SOURCE NAMES NO BRANCH", which is untrue where git completes the source to a branch. It is a shipped tool, so it is left for scripts/shape_materialize.py: the docstring ofgives_a_branch_another_namesays "ANY OTHER SOURCE NAMES NO BRANCH", but git completes a source such asrefs/hto a branch, and its carried refspec's fetch exits 128 beside a branchhy(#1235 follow-up) #1238; this PR is wording only, in the test file.Rows failing on main: none. No row is added or changed, so there is nothing for main to fail. Mutants: none, because no behaviour changed;
carried-refs-h-not-a-patternis the same row, and the syntax tree below shows nothing outside the docstring moved.Round 1, after the review rv1235
refs/hclashes "like any carried source". A carried branch does not clash onto its own name, so "any" was untrue. It now says the fetch of the source clashes "as a pull request's ref does", where its destination is a branch's name.h. Both now sayrefs/hitself or a ref git completes it to, "such as" the branchrefs/heads/refs/hor the tagrefs/tags/refs/h, with the refs spelled. The docstring says the fetch clashes (not the ref), and its citation, "(the re-check of shape_materialize.py and bump-leg.py: the fetch for a branch's answer leaves out a pattern likerefs/heads*that puts a branch under another name, its clauses move into_left_out, and the docstrings name the clashes left and the way back (#1100) #1157, NIT 1)", follows that clause in parentheses.refs/h" is replaced by the paragraph above: the one code sentence that does cover it is left for scripts/shape_materialize.py: the docstring ofgives_a_branch_another_namesays "ANY OTHER SOURCE NAMES NO BRANCH", but git completes a source such asrefs/hto a branch, and its carried refspec's fetch exits 128 beside a branchhy(#1235 follow-up) #1238.Runs
All through the lane's runner
run9.sh(stubghfirst on PATH,GIT_SSH_COMMAND=false,GIT_CONFIG_GLOBAL=/dev/null), on the committed head81582301ewith the tree clean (dirty=0), Python 3.12.3. Thegiton that runner's PATH is/usr/bin/git, git 2.43.0 (measured withcommand -v gitandgit --versionunder the runner's PATH). The review's own runs had git 2.47.1 first on PATH and gave the same counts.python3 -I,ast.dump): the file at this head and on main0ed3e57f8, each with the docstring oftest_which_clause_leaves_each_refspec_outremoved, are equal (75050 characters of dump both). A control that renamesWHICH_CLAUSEreports them different (75050 against 75052).-k carried-refs-h-not-a-patternovertests/test_family_bump_fetch_refspecs.pyandtests/test_bump_leg_fetch_refspecs.py: 2 passed, 123 deselected, as at368b87e9b.tests/test_repo_hygiene.pyandtests/test_path_guard_hygiene.py: 222 passed.git grep -n 'which is no branch' -- tests/test_family_bump_fetch_refspecs.py: finds nothing at this head (it finds lines 582 and 691 on main). The one other line of the file that has bothrefs/hand "no branch" is line 691, where "no branch" is said ofrefs/headsx/.Merge-trees:
git merge-tree --write-tree origin/main HEADis clean (exit 0). Main was0ed3e57f8when read, and the merge base ise04826db4; main's one commit since touches none of the three files named here. Of the 49 open PRs, only this one touchestests/test_family_bump_fetch_refspecs.py(read fromgh pr list --json files; the largest has 9 files).Closes #1230
Lane: openreposhape-5 (openRepoShape-5)
🤖 Generated with Claude Code
Summary by Sourcery
Enhancements:
refs/hsource ref and when its fetch conflicts with an existing destination.