# `muse push` — have-negotiation ignores sibling refs on remote ## Background When pushing a branch to a remote, the push negotiation computes `blobs_to_send` by comparing the local tip against the remote's tip for that specific branch only. It does not account for objects already present on the remote via other refs. ## Observed behaviour After pushing `dev` to staging successfully (17 commits, 46 blobs), pushing `main` to the same staging remote attempted to upload 1,375 commits and 379 MB of data — failing with `[Errno 32] Broken pipe`. Local `main` is `staging/dev` + one merge commit. The merge-base of local main and local dev is exactly dev's tip (`sha256:f9828e…`). All objects are already present on staging from the dev push. Only the merge commit itself needs to go over the wire. ## Root cause The "have" set used during push negotiation is scoped to the target branch's remote tip. Objects reachable from other remote refs (e.g. `staging/dev`) are not included in the have set, so the delta computation over-counts `blobs_to_send` by treating already-uploaded objects as missing. ## Expected behaviour `blobs_to_send` should be computed against the union of all objects reachable from all refs present on the remote — not just the branch being pushed. When `main` is a direct descendant of `dev` and `dev` is already on the remote, the push for `main` should send only the new commits and their net-new objects (in this case, one merge commit and zero new blobs). ## Impact - Pushes to branches that lag behind a sibling ref on the same remote become disproportionately large. - Large packs time out or hit broken-pipe errors even when no new data is needed. - Workaround: push the most-advanced branch first (e.g. `dev`), then accept that `main` may still require a large redundant upload until this is fixed.