Skip to content

fix: split refspecs on the last colon, like Git does - #2888

Merged
Sebastian Thiel (Byron) merged 2 commits into
GitoxideLabs:mainfrom
ameyypawar:refspec-last-colon
Aug 6, 2026
Merged

fix: split refspecs on the last colon, like Git does#2888
Sebastian Thiel (Byron) merged 2 commits into
GitoxideLabs:mainfrom
ameyypawar:refspec-last-colon

Conversation

@ameyypawar

Copy link
Copy Markdown
Contributor

Created by Claude Code on behalf of Amey, who reviewed it before submitting. Everything below this line is the agent's writing, not his.


Summary

  • Split a refspec on the last colon rather than the first, so that a push source may contain one itself.
  • Cover multi-colon specs for both operations in the parse baseline, and regenerate both of its archives.

Git baseline

parse_refspec() in refspec.c finds the separator with rhs = strrchr(lhs, ':'), so everything before the final colon is the source. That matters for push, where the source is a revision rather than a ref name, and revisions may contain colons — :/message searches commit messages, and <rev>:<path> addresses a blob or tree.

Both work in Git today:

$ git push origin ':/findme-marker:refs/heads/viaregex'
 * [new branch]      :/findme-marker -> viaregex

gix-refspec split on the first colon, so it read the destination as findme-marker:refs/heads/viaregex, rejected that as an invalid reference name, and the spec never parsed.

Fetch is unaffected: its source is a ref name, which cannot contain a colon, so Git rejects the same inputs there. The added baseline entries cover both directions.

Validation

parse_baseline.sh runs every spec through real Git via git ls-remote, so the six new entries record Git's own verdict rather than an expectation. Reverting the change makes that test fail with Out of 84 baseline entries, got 80 right, (4 mismatches and 0 panics) — the four push forms.

before after
cargo test -p gix-refspec 76 passed, 0 failed 77 passed, 0 failed
same, with GIX_TEST_FIXTURE_HASH=sha256 76 passed, 0 failed 77 passed, 0 failed
cargo test -p gix 417 passed, 0 failed 417 passed, 0 failed
cargo fmt --check -p gix-refspec clean clean

Both parse_baseline.tar and parse_baseline_sha256.tar are regenerated. The archive identity is derived from the fixture script, so leaving the second one stale would have it rewritten on the next local run of just unit-tests, which exercises this crate under sha256.

One thing stays divergent, and it isn't the split: ::a parses in Git because a non-glob push source is not validated at all — /* anything goes, for now */ — while gix-refspec requires the source to be a ref name or a revision. That is unchanged here.

cargo clippy -p gix-refspec cannot be run on its own in this checkout; it stops on gix-hash's own compile_error! about hash feature selection, which is unrelated to this change.

Amey Pawar (ameyypawar) and others added 2 commits August 6, 2026 20:04
`parse_refspec()` in `refspec.c` locates the separator with
`rhs = strrchr(lhs, ':')`, so everything before the final colon is the source.
That matters for push, where the source is a revision rather than a ref name and
may itself contain a colon - `:/message` searches commit messages, `<rev>:<path>`
addresses a blob or tree. Both are accepted by Git today.

Splitting on the first colon instead made `:/message:refs/heads/x` parse as the
destination `message:refs/heads/x`, which is not a valid reference name, so the
spec was rejected outright.

Fetch is unaffected, as its source is a ref name that cannot contain a colon.
Baseline entries cover both operations; both archives are regenerated because the
archive identity derives from the fixture script.
 - update baseline archives
@Byron

Copy link
Copy Markdown
Member

Thanks a lot, great catch!

One thing stays divergent, and it isn't the split: ::a parses in Git because a non-glob push source is not validated at all — /* anything goes, for now */ — while gix-refspec requires the source to be a ref name or a revision. That is unchanged here.

This sounds like a bug in Git? If not, let's haeve a PR

@Byron
Sebastian Thiel (Byron) merged commit 04b91a1 into GitoxideLabs:main Aug 6, 2026
26 of 56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants