Update docs: target HEAD detection landed, mismatch is observable · Entire
Update docs: target HEAD detection landed, mismatch is observable
f682d3e·
Soph·2mo ago·1 file·+25 added/-17 removed
usage.md now describes both sourceHead and targetHead, the upload-pack round-trip behind the target side, and the three practical mitigations for a default-branch mismatch:
- match defaults at init time (preferred)
- set HEAD manually post-sync (host API or git symbolic-ref)
- script around the probe output to detect mismatches before sync
The receive-pack-omits-HEAD limitation note moves to a smaller side remark; we now work around it rather than calling it a follow-up.
Refs #45.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
Sessions
120ccae292d5View transcript
[?
do we have integration tests?Claude Code·Opus 4.7[1m]·1 step](/content/gh/entireio/git-sync/session/d0406407-d612-489d-b375-1372d062af82#timeline-120ccae292d5/index.html)
Changes
1
docs
Musage.md+25/-17
223 unmodified lines
## HEAD / Default Branch
git-sync surfaces the source's symref HEAD target — the source's default branch — in the result's `execution.sourceHead` field (JSON) and as a `source-head: <ref>` line in human output. `probe` exposes the same field.
git-sync surfaces both sides' symref HEAD targets in result output:
- JSON: `execution.sourceHead` and `execution.targetHead` (sync / plan / replicate / bootstrap); `sourceHead` / `targetHead` (probe).
- Human: `source-head: <ref>` and `target-head: <ref>` lines.
```
$ git-sync sync --json … | jq .execution.sourceHead
"refs/heads/main"
$ git-sync probe --target-url <target> --json | jq '{sourceHead,targetHead}'
{
"sourceHead": "refs/heads/main",
"targetHead": "refs/heads/master"
}
```
Target HEAD is read via a separate `upload-pack` info-refs round-trip against the target URL, since the `receive-pack` advertisement we use for push setup omits HEAD by protocol design. The round-trip runs concurrently with the existing target setup; failures (push-only auth that 401s on upload-pack, empty bare targets where HEAD's underlying ref doesn't yet exist) leave `targetHead` empty rather than failing the sync.
The target's default branch is **not** automatically reconciled. git's `push --mirror` doesn't propagate HEAD either; standard receive-pack has no portable mechanism for setting a remote symref's target (only newer git versions support a `symref-update` capability, and go-git's current alpha doesn't send it). The result: if you `git init --bare` your target with a default branch that differs from the source's, the mirror's HEAD will dangle even after a successful sync.
`push --mirror` doesn't propagate HEAD either; the only portable wire-level mechanism is the newer `symref-update` receive-pack capability, which go-git's current alpha doesn't implement. So if you `git init --bare` your target with a default branch that differs from the source's, the mirror's HEAD will dangle even after a successful sync.
Practical mitigations, in order of preference:
1. **Match the default at init time.** `git init --bare --initial-branch=<source-default>` (or the equivalent on your host) avoids the problem entirely. Compare against `git-sync probe <source-url>`'s `sourceHead` to know what to pass.
2. **Set HEAD manually post-sync.** On a self-hosted bare repo: `git symbolic-ref HEAD refs/heads/<source-default>`. On hosted providers (GitHub, GitLab, etc.), use the provider's API or web UI to set the default branch.
3. **Compare the fields.** A wrapper script that runs `git-sync probe ...` and compares `sourceHead` against `targetHead` will catch mismatches before they bite.
Detecting the mismatch automatically is tracked as a follow-up; doing so requires a separate `upload-pack` round-trip against the target since the `receive-pack` advertisement we already query doesn't include HEAD.
## JSON Output
Add `--json` to any command to emit machine-readable output instead of the default text format.
4 unmodified lines
- refs and hashes are serialized as strings, not raw byte arrays
- top-level keys include `plans`, `pushed`, `skipped`, `blocked`, `deleted`, `warned`, `dryRun`, `protocol`, and `stats`, plus `relay`, `relayMode`, `relayReason`, `batching`, `batchCount`, `plannedBatchCount`, and `tempRefs`
- each item in `plans` includes stable string fields such as `branch`, `sourceRef`, `targetRef`, `sourceHash`, `targetHash`, `kind`, `action`, and `reason`
- `execution.sourceHead` (sync/plan/replicate/bootstrap) and `sourceHead` (probe) carry the source's symref HEAD target when advertised
- `execution.sourceHead` / `execution.targetHead` (sync/plan/replicate/bootstrap) and `sourceHead` / `targetHead` (probe) carry each side's symref HEAD target when advertised
## Auth