A remote-tracking ref row must identify BOTH the remote host AND the remote branch, in full absolute form (?/project/branch/…) — but the JS writer drops the branch: shared/ingest.js saveRemoteRef (and clone/add) do remoteUri.replace(/\?.*/, "?"), recording //host?#tip with the query stripped to a bare ?. So every branch of one host collapses onto the trunk key even though store.eachRemote keys by authority + query and COULD tell them apart: a second branch push overwrites the first, and a cached be head //origin?branch cannot resolve the right per-branch tip. Fix: record {verb:"get", uri: <scheme>://<host>?/<abs-branch>#<tip>} — host kept, branch kept and RESOLVED to absolute — across every remote-track writer. Split from GIT-016 T3 (saveRemoteRef); JS only (be/, via jab). Method: work.
shared/ingest.js saveRemoteRef(shard, remoteUri, tip) writes {verb:"get", uri: remoteUri.replace(/\?.*/,"?") + "#" + tip} — the \?.*→? strip discards the branch, so the row is //host?#tip (host present, branch GONE).ingest.clone/add do the SAME origin = remoteUri.replace(/\?.*/,"?") strip — the whole remote-track convention loses the branch, not just the push path.store.eachRemote (shared/store.js ~L451) keys rows by (u.authority) + (u.query) + "#"; the reader ALREADY distinguishes branches — the WRITER is the defect. With query stripped to ?, two branches of one host share one key and the newer clobbers the older.saveRemoteRef: verbs/post/post.js pushRemote, verbs/put/put.js pushWire, and (GIT-016 T4) the head verb — all inherit the branch loss.?/project/branch/…), never a bare ? and never a relative branch.store.eachRemote / a cached be head //origin?branch / get's remote-track resolve return the correct PER-BRANCH tip; multiple branches of one host coexist.be/, run via jab. Do NOT run native be; do NOT open beagle/.?/project/branch shape, see URI); do NOT hand-assemble ref strings. Reuse resolveRef/the ref resolution already shared in GIT-016.GIT-017 comments, greppable, ticket-coded ≤64-char commit. No new deps.clone/add/get's cached-read + update path working — the ?-strip is an established convention there; changing it must not regress a fresh clone's default-branch row./project/branch): a relative/bare form is ambiguous once detached from the push context, and eachRemote's key needs a stable per-branch discriminant.? (the trunk), but a branch-scoped fetch/push must record that branch — decide the split in clone/add vs saveRemoteRef.store.eachRemote yields two distinct tips (today the second clobbers the first under the trunk key).saveRemoteRef to keep host + full-absolute branch (stop the \?.*→? strip; resolve the branch to ?/project/branch).clone/add's same strip: keep the default-branch ? row where correct, record the branch where a branch was fetched.be head //origin?branch + get's remote-track resolve pick the right per-branch tip; run the wire bucket.?-strip is shared by clone/add/saveRemoteRef; touching it risks get's cached-read/update path — cover those in the regression.relate.resolveRef) for the absolute-branch form.