Fetching +HEAD:<dst> over gix's file:// transport resolves the source
HEAD against the calling repository when the caller is non-bare and shares
the upstream's default branch name, instead of against the remote. The
destination ref ends up at the local tip and upstream objects are never
transferred.
Real git fetch against the same two repositories resolves HEAD against the
remote, so this is a gix deviation, not a protocol ambiguity.
Upstream: GitoxideLabs/gitoxide#2613
Impact
fetch_vendor uses +HEAD:<dst> to capture the upstream default branch when
no explicit ref is configured. Against a non-bare caller sharing the upstream's
branch name, the fetch silently succeeds with the wrong OID and no upstream
objects in the local odb.
Reproducer
crates/git-vendor/tests/gix_fetch_head_symref.rs — three tests: a real-git
oracle, the bug demo (#[should_panic] until upstream is fixed), and a
bare-caller control showing the working path.
Assisted-by: Claude:claude-opus-4-7
Fetching
+HEAD:<dst>overgix'sfile://transport resolves the sourceHEADagainst the calling repository when the caller is non-bare and sharesthe upstream's default branch name, instead of against the remote. The
destination ref ends up at the local tip and upstream objects are never
transferred.
Real
git fetchagainst the same two repositories resolvesHEADagainst theremote, so this is a
gixdeviation, not a protocol ambiguity.Upstream: GitoxideLabs/gitoxide#2613
Impact
fetch_vendoruses+HEAD:<dst>to capture the upstream default branch whenno explicit ref is configured. Against a non-bare caller sharing the upstream's
branch name, the fetch silently succeeds with the wrong OID and no upstream
objects in the local odb.
Reproducer
crates/git-vendor/tests/gix_fetch_head_symref.rs— three tests: a real-gitoracle, the bug demo (
#[should_panic]until upstream is fixed), and abare-caller control showing the working path.
Assisted-by: Claude:claude-opus-4-7