Repository navigation
The for-each-ref ordering was pinned but its RELATION was never modelled - #9509
Merged
Merged
Conversation
added 2 commits
August 27, 2026 20:23
…tewise and our comparator is code-point-wise
Side-chat review accepted this PR's factual content and said mechanisation
was owed. It was: the two commits before this one were prose, and the claim
they make -- that our code-point comparator agrees with git's bytewise order
-- had no executing evidence.
The existing ordering witnesses establish that the check refuses a
DECREASING pair. They say nothing about WHICH ORDER is being enforced,
because their fixtures are pure ASCII and every plausible comparator agrees
there.
THE DISCRIMINATING PAIR IS ASCII-vs-MULTIBYTE, chosen to separate our
comparator from the one substitution the annotation warns about:
"refs/heads/z" vs "refs/heads/e-acute" (U+00E9, bytes C3 A9)
bytes 0x7A < 0xC3 -> z first
code points 0x7A < 0xE9 -> z first
locale e-acute sorts near "e", BEFORE z
A locale-aware comparator therefore disagrees with git on exactly this pair,
and it is the change that would look like an improvement. Both rows fail if
anyone makes it: ascending would refuse, descending would be accepted.
13 witnesses PASS.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 28, 2026
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.
Raised by the operator on #9506, and the answer turned out to be more interesting than either "it is documented" or "it is not".
What was already right
git.Core.ForEachRefInpins--sort=refnamein its transport argv — the order is not inherited from a default, it is requested. There is a citedExternalAuthorityatgit-scm.com/docs/git-for-each-ref. Andextdeps.git.enumerationdeliberately validates the order rather than imposing it, so the flag stays falsifiable: a decoder that sorted its own rows would make the pin decorative, and deleting--sort=refnamewould leave every witness green.None of that changes here.
What was missing
Pinning the flag fixes the ORDER and says nothing about the RELATION — and a consumer has to reimplement that relation in order to check it. Ours does:
git-check-ref-format(1)constrains which bytes may appear and says nothing about an encoding.string_is_lexicographically_before->string_lex_comparecompares code points (code_point(char_at(s, 0)), recursing).Those are two different relations from two different authorities, equated by adjacency. They do agree — because UTF-8 is order-preserving: a code point's encoding sorts, byte for byte, in the same relation as the code point itself. That is a property of the encoding, not of either comparator, and it was written down nowhere.
Why that is worth a change rather than a shrug
The check is correct today and reads as coincidence, which fails in a specific and nasty direction: make
string_lex_comparelocale-aware — an entirely reasonable-looking improvement — and the decoder starts refusing validfor-each-refoutput with "ref names are not strictly increasing", a message that accuses git rather than the change that broke it. The reader who investigates begins at the wrong end.So the relation is now stated at both ends: the upstream half beside the operation that pins the flag, and the mismatch named at the check that relies on it.
Two gaps declared rather than papered over
Non-UTF-8 refnames. git permits them; a code-point comparator has no defined relation to them. No refusal is claimed, because whether such a name survives the shell transport into a
Stringat all is unestablished, and a wall whose reachability has not been measured is asserted coverage rather than a wall (§4b). The next rung here is a measurement, not a check — and saying so is the point, since the tempting move is to add a guard that might be permanently green.No git version is pinned.
ExternalAuthoritycarries aUriand nothing else — there is no version field to pin one with. §3 asks an extdeps subject to declare its version, so this is a standing gap for the whole module, named here because sort semantics are exactly the kind of fact that is version-relative. Not fixed here: adding a version axis toExternalAuthoritytouches every citation in the corpus and belongs in its own change.Scope
Annotations only — no type, function, argv or emitted byte changes. Deliberately not folded into #9506, which consumes this decoder: a correction to a merged module should not arrive inside a feature that depends on it.
— sent from calm-ram-380