Transfer
Transfer moves objects and refs between repositories. The goal is to send exactly the objects the other side lacks, as one pack, and then update refs safely.
Fetch and clone
Section titled “Fetch and clone”A fetch has four steps:
- Advertisement. The server lists its refs and their IDs.
- Negotiation. The client sends
wantlines for the commits it needs andhavelines for commits it already has, newest first. The server acknowledges commits it also has. When they have found enough common commits, the client sendsdone. - Pack. The server walks from the wanted commits, stops at the common ones, and sends one pack holding exactly the missing objects.
- Update. The client writes the pack and its index, checks that every object it now claims to have is present, and updates refs according to the remote’s refspecs.
A refspec maps remote names to local ones. +refs/heads/*:refs/remotes/origin/* copies every remote
branch to a remote-tracking ref under
refs/remotes/origin/; the + allows updates that aren’t fast-forwards, since the remote’s branch
may have been rewritten.
Protocol v2 (protocol.version=2, the default since Git 2.26) restructures the conversation
into commands. Its ls-refs command lets the client ask only for the refs it cares about, which
matters on servers with hundreds of thousands of refs. A partial clone (--filter=blob:none)
asks the server to leave out file contents and fetches them later on demand.
Clone is git init, then adding the remote, a fetch, and a
checkout of the default branch.
girtPartialProtocol v0 and v2, depth and pruning; HTTP sends all haves in one round, tags aren’t followed, FETCH_HEAD isn’t written, and partial clone isn’t supported.issue #505
Push runs the other way. The server advertises its refs; the client sends commands such as “update
refs/heads/main from X to Y” plus a pack of the objects the server lacks, worked out with a
history walk from Y excluding what the
server already has.
The server checks each update. By default it refuses one that isn’t a
fast-forward unless the client forces
it, and server hooks can refuse anything. It replies ok refs/heads/main or
ng refs/heads/main non-fast-forward per ref. A push can partly succeed, so the per-ref status
matters. git push --force-with-lease adds a check that the remote ref still holds the value you
last fetched, so you don’t overwrite someone else’s work.
girtSupportedAPI docs
Transports
Section titled “Transports”The same protocol runs over three transports:
- Local: the remote is a path on disk,
/srv/repo.gitorfile:///srv/repo.git. Git runs the server side as a local process, or for a plain-path clone hard-links the object files. - Smart HTTP(S): the client requests
GET /info/refs?service=git-upload-packfor the advertisement, thenPOST /git-upload-pack(fetch) orPOST /git-receive-pack(push). - SSH: the client runs
ssh host git-upload-pack 'repo.git'(orgit-receive-pack) and speaks the protocol over the connection.
girtSupportedLocal is built in; HTTP and SSH are the http and ssh features. HTTP/SSH v2 clients are Git-verified. SSH uses system OpenSSH on macOS and Linux; intermittent fixture exits remain under investigation.API docs