this should work right, or did the syntax change:

Codex·GPT-5.4·Soph·5mo ago·1hr 5min·2 Checkpoints·6 file changes·+270/-11·3.3M tokens

this should work right, or did the syntax change:

❯ go run ./cmd/git-sync sync
--protocol v2
--measure-memory
-v
--target-username git
--target-insecure-skip-tls-verify
--tags
https://github.com/kubernetes/kubernetes.git
https://localhost:8080/git/test/git-sync-smoke-8 error: list target refs: pkt-line 1: cannot read hash, pkt-line too short (# service=git-receive-pack) exit status 1

5mo ago·6.0s

I’m checking the current CLI and sync path in this repo first, then I’ll trace where that git-receive-pack pkt-line error is coming from to tell you whether this is syntax or protocol behavior.

The flags are still present, so this is not a simple flag rename. I’m checking whether sync still accepts positional URLs and whether the failure is actually the target speaking the wrong Git service on the wire.

The CLI still accepts your exact flag names and also still accepts positional <source-url> <target-url>. The error points at target ref discovery, so I’m narrowing this to the HTTP/Git service mismatch rather than argument parsing.

The target side is discovered with a receive-pack info/refs call, exactly where your error says it breaks. I’m checking the HTTP transport code next to see what response shape it expects and why # service=git-receive-pack is being treated as malformed.

I’ve confirmed one important detail from this codebase: --protocol v2 only affects the source side. The target is always queried via v1 receive-pack discovery, so your failure is unrelated to target protocol selection and more likely means the target endpoint returned an unexpected smart-HTTP advertisement.

The repo’s own docs still describe this Entire-local path as supported, including --protocol v2 against a local Entire target. That makes the current failure look even more like a server-side advertisement quirk or a client-side decoder edge case, not a CLI syntax drift.

I have enough to answer the syntax question. I’m doing one last check against the target endpoint shape so I can tell you whether the command itself is valid but the server response is malformed.

Your command syntax is still valid.

sync still accepts:

  • --protocol
  • --measure-memory
  • -v
  • --target-username
  • --target-insecure-skip-tls-verify
  • --tags
  • positional <source-url> <target-url>

That’s in cmd/git-sync/main.go and the positional URL fallback is in cmd/git-sync/main.go.

The failure is lower-level than CLI parsing. sync is dying while listing target refs via target receive-pack discovery in internal/syncer/syncer.go. So this is the target endpoint or its response shape, not a changed flag.

Two useful details:

  • --protocol v2 only applies to the source side here; target discovery is still v1 receive-pack smart HTTP. That matches the README and code in internal/gitproto/refs.go.
  • The specific error suggests the target returned an unexpected info/refs?service=git-receive-pack advertisement, or auth/endpoint routing caused a non-standard response to be parsed as Git pkt-lines.

Most likely things to check:

  • target URL is the actual Git smart-HTTP repo endpoint for push, not a UI/API route
  • target auth is present; for Entire that usually means --target-token or --target-bearer-token, unless your local credential lookup is configured
  • the server’s GET <target>/info/refs?service=git-receive-pack response is a valid smart-HTTP advertisement

So: syntax did not change. The command is fine; the target receive-pack discovery is what looks wrong.

this is the exact same command that worked before, same source, same target (but new repo)

5mo ago·13.6s

Then the likely change is not CLI syntax and not the source side. It’s one of these:

  • the new target repo is being served differently when empty
  • the target auth/resolution path changed for this repo
  • the target’s receive-pack info/refs response regressed

The error is very specific: git-sync got as far as target ref discovery and then failed decoding the git-receive-pack advertisement. In this codebase, that happens before any push logic. A brand-new repo is the strongest clue: empty-target handling on the server side is the thing that differs from your previously working repo.

What I’d check first:

  • Run git ls-remote https://localhost:8080/git/test/git-sync-smoke-8
    • if that fails, the repo endpoint itself is wrong or not fully initialized
  • Run a raw check against:
    • GET https://localhost:8080/git/test/git-sync-smoke-8/info/refs?service=git-receive-pack
    • it should return a valid smart-HTTP advertisement, not an HTML page, JSON error, or truncated pkt-line stream
  • Compare the new repo with an older repo that worked:
    • same path shape
    • same auth requirements
    • same backend initialization for empty repos

One more important point: your command only sets --target-username git, not a token. That can still work if credentials are being discovered implicitly, but if the new repo is behind a slightly different auth path, the server may be returning something non-Git and the pkt-line decoder is choking on it.

So I would not change the command syntax. I would debug the new repo’s receive-pack advertisement and auth path. If you want, I can patch git-sync to log the first bytes of the target info/refs response on decode failure so this becomes obvious immediately.

we did do a pretty big rewrite of the code base since I last run this, so maybe any idea where this could have been broken?

5mo ago·16.4s

I’m looking for places where the rewrite changed target discovery or empty-target behavior, because the error occurs before any actual sync work. The strongest suspects are the new target receive-pack probe path and how empty advertisements are decoded.

The rewrite likely moved the break into session setup. I’m checking the refactor commits around newSession and target discovery, because that’s where the current failure path was introduced.

Yes. The most plausible break is in the rewritten target setup path, not the CLI.

Best candidate:

  • internal/syncer/syncer.go
    • newSession() now always does target ref discovery up front with gitproto.AdvertisedRefsV1(..., transport.ReceivePackService).
    • Your error happens exactly there: list target refs.

Why this is suspicious:

  • this runs before the bootstrap/empty-target decision in internal/syncer/syncer.go
  • so if the new repo’s empty receive-pack advertisement is slightly unusual, the sync dies before it can decide “empty target, use bootstrap relay”

Second candidate:

That decoder path is brittle if Entire now returns any nonstandard-but-close receive-pack response for a fresh repo:

  • banner-only
  • missing flush after # service=git-receive-pack
  • empty repo advertisement shaped differently from the in-memory test server
  • auth/error body that still starts with Git-ish text

Third candidate:

  • internal/gitproto/smarthttp.go
    • RequestInfoRefs() no longer validates response content type or logs bad bodies
    • so a misrouted HTML/JSON/auth response becomes a pkt-line decode error, which is exactly the kind of opaque failure you saw

So if I had to bet, I’d put it on:

  1. newSession() always probing target receive-pack
  2. decodeV1AdvRefs() not tolerating an empty/new Entire repo advertisement shape

What I would change first:

  • on target receive-pack decode failure, log the first 200 raw bytes and content type
  • if the response is effectively “service banner + no refs”, treat it as empty target instead of fatal
  • add an integration test for an empty target whose receive-pack info/refs is banner-only or otherwise sparse

If you want, I can make that diagnostic patch now and likely also harden empty-target handling in the same spot.

yes, do this

5mo ago·9.5s

I’m patching the target discovery path now. First I’m checking how the underlying packp decoder treats sparse advertisements so I can make the fallback precise instead of papering over unrelated decode failures.

I found a concrete weakness: decodeV1AdvRefs() currently feeds the raw info/refs body straight into packp.AdvRefs.Decode, while go-git’s own HTTP transport first strips the smart-HTTP # service=... header and tolerates empty advertisements after that. I’m aligning our decoder with that behavior and adding a focused regression test.

I’m editing the decoder now. The change is small but targeted: normalize smart-HTTP v1 advertisements the way go-git’s transport does, then preserve a short raw-body preview in failure messages so the next mismatch is immediately visible.

The decoder patch is in and formatting is clean. I’m running the gitproto and syncer test suites now to make sure the new empty-advertisement handling didn’t change normal behavior.

The one failing test is useful: after a valid smart header plus flush, packp.AdvRefs.Decode returns empty input instead of ErrEmptyAdvRefs on this library version. I’m tightening that case so a banner-only empty target is treated as empty remote, which is the behavior we want.

internal/gitproto is green with the new regression tests. I’m waiting for internal/syncer to finish so we know the broader sync flow still behaves the same.

I changed the v1 advertisement decoder in internal/gitproto/refs.go so it now:

  • consumes the smart-HTTP # service=... header explicitly before decoding refs
  • treats a header-only / banner-only advertisement as an empty remote instead of a hard decode failure
  • includes a short raw body preview on malformed decode errors

I also added regression coverage in internal/gitproto/refs_test.go for:

  • smart empty receive-pack advertisements
  • malformed bodies that should surface a preview in the error

Verification: go test ./internal/gitproto ./internal/syncer passed.

This should address the most likely rewrite regression for a brand-new target repo. Re-run the same go run ./cmd/git-sync sync ... command; if it still fails, the new error should now show the first bytes of the target info/refs response, which will make the next issue obvious.