Public: anyone can read this; the crew can change it.

Big repos always clone: transfers end on stalled progress, not a 5-minute clock, and partial clone works #4482

shipped production is serving it opened this has it
opened this

Why now. Full HTTPS clones of trevato/arm (an SO-ARM100 fork with large STEP/STL CAD files) from the public forge die partway through: RPC failed; curl 56 Recv failure: Connection reset by peer … early EOF. git clone --filter=blob:none warns filtering not recognized by server. Probed today, 2026-10-21. The research team traced it to two causes in the code:

  1. The 5-minute kill timer. Anonymous transfers run under limits.transferTimeoutMs = 300 000 ms (src/http/strangers.ts:61). src/git/smart-http.ts:136-139 SIGKILLs git upload-pack when it fires. A CAD pack that takes more than 5 minutes over a slow link gets killed mid-stream. Signed-in transfers get 600 s, which is only a later wall.
  2. No partial clone. gitEnv blanks the system and global config (src/git/env.ts:22-25), and nothing sets uploadpack.allowFilter. So stock git can't skip big blobs.

Done when:

  • Progress-based deadline. Transfers end on lack of progress, not wall clock. Kill only when fewer than N KiB have moved in the last 30 s; keep a generous absolute cap of 2 h. The stranger pool share stays exactly as it is. This loosens slow-but-moving clones only and leaves the abuse limits alone.
  • Partial clone. uploadpack.allowFilter=true and uploadpack.allowAnySHA1InWant=true are passed to upload-pack (via -c, so the blanked global config stays blank). git clone --filter=blob:none and --filter=blob:limit=1m of a repo then works, and later git checkout fetches the missing blobs lazily. Test it over smart HTTP and SSH.
  • Read permission on lazy fetches. A lazy blob fetch is an ordinary upload-pack want and goes through the same read check as a clone. Add a test that a private repo's blob can't be fetched by OID without read access.
  • Tests:

- A 200 MB repo cloned through a 1 MB/s throttle finishes, where it is killed today. - The filtered clone gets no blobs above the limit, and a later checkout fills them in. - A transfer that stalls for 30 s is still killed.

  • Docs. docs/APPS.md (or a new docs/GIT.md) says how to clone a big repo: git clone --filter=blob:none <url>.

The full design is in the large-files epic (#4481). This issue is the part that unblocks the arm today with stock git and no new protocol.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs