Self-Healing CI: Recovering a Git Clone That Hangs on a Large Repo
A clone that stalls on a big repository is a stuck transfer, not a broken repo -- a retry, often shallow, usually completes it.
The problem
A git clone of a large repository hangs and is eventually killed by a timeout, or stalls at a fixed percentage and drops. The repository and ref are valid; the long transfer stalled under a brief network or server-side condition. A human re-runs the job -- often with a shallow clone -- and it completes unchanged.
Cloning into 'big-repo'...
remote: Compressing objects: 100% ...
# stalls here, then: fatal: early EOF / the step times outWhy it happens
Cloning a large repo moves a great deal of data over one long-lived connection, and the longer the transfer, the more exposed it is to a brief network stall, a server-side pack-generation slowdown, or memory pressure on the remote that causes it to hang or drop mid-stream.
The stall reflects the size of the transfer meeting a transient condition, not a problem with the repository: a retry, especially a shallow or filtered clone, shrinks the transfer window and completes.
The manual fix
Manual mitigations for a stalled large clone:
- Re-run the job to retry the clone.
- Shallow-clone (
--depth=1) or use a partial clone (--filter=blob:none) to shrink the transfer. - Wrap the clone in a bounded retry so one stall does not fail the step.
git clone --depth=1 --filter=blob:none <url> || (sleep 5 && git clone --depth=1 --filter=blob:none <url>)How this gets automated
A stalled clone has a recognizable signature -- a long transfer that hangs or drops -- and the safe response is to retry, ideally with a smaller transfer. A self-healing CI pipeline detects the stalled or timed-out clone, retries with backoff, and only escalates if the repository is genuinely unreachable, distinguishing a transient stall from a real access problem.