Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
82 views
in Technique[技术] by (71.8m points)

How does Git's transfer protocol work

I am working with Git for more than one year and now I have to explain it to others in our group. That is why I need a bit more backround. I went thourgh most of the Git Book in the last year and recently I continued with chapter 10. In chapter 10.6 I got completely stuck:

Let’s follow the http-fetch process for the simplegit library:

$ git clone http://server/simplegit-progit.git

The first thing this command does is pull down the info/refs file. This file is written by the update-server-info command, which is why you need to enable that as a post-receive hook in order for the HTTP transport to work properly:

=> GET info/refs
ca82a6dff817ec66f44342007202690a93763949     refs/heads/master

I have a small test repo https://github.com/to_my/repo and git clone works well. But

  • Where is the folder info/refs? I only find a /.git/info/exclude afther the clone...
  • How should I use the update-server-info command? Is it part of git clone somehow?
  • I am competely lost with "...which is why you need to enable that as a post-receive hook" although I understand hooks (I thought) and use a pre-commit hook for automatically increasing the package version.
  • I can't get the command GET info/refs in git bash work.

Sorry if the questions are stupid, but I just don't understand how to put these pieces from the documentation together.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Note: starting Git 2.18 (Q2 2018), the git transfer protocol evolves with a v2 which is implemented.
With Git 2.26 (Q1 2020), it is the default. It is not in 2.27 (Q2 2020, see the end of this answer, and the follow-up answer). It is again in 2.28 (Q3 2020)

See commit a4d78ce, commit 0f1dc53, commit 237ffed, commit 884e586, commit 8ff14ed, commit 49e85e9, commit f08a5d4, commit f1f4d8a, commit edc9caf, commit 176e85c, commit b1c2edf, commit 1aa8dde, commit 40fc51e, commit f7e2050, commit 685fbd3, commit 3145ea9, commit 5b872ff, commit 230d7dd, commit b4be741, commit 1af8ae1 (15 Mar 2018) by Brandon Williams (mbrandonw).
(Merged by Junio C Hamano -- gitster -- in commit 9bfa0f9, 08 May 2018)

The full specification is in Documentation/technical/protocol-v2.txt:

Protocol v2 will improve upon v1 in the following ways:

  • Instead of multiple service names, multiple commands will be supported by a single service
  • Easily extendable as capabilities are moved into their own section of the protocol, no longer being hidden behind a NUL byte and limited by the size of a pkt-line
  • Separate out other information hidden behind NUL bytes (e.g. agent string as a capability and symrefs can be requested using 'ls-refs')
  • Reference advertisement will be omitted unless explicitly requested
  • ls-refs command to explicitly request some refs
  • Designed with http and stateless-rpc in mind. With clear flush semantics the http remote helper can simply act as a proxy

In protocol v2 communication is command oriented.
When first contacting a server a list of capabilities will advertised. Some of these capabilities will be commands which a client can request be executed. Once a command has completed, a client can reuse the connection and request that other commands be executed.

info/refs remains server endpoint to be queried by a client, as explained in HTTP Transport section:

When using the http:// or https:// transport a client makes a "smart" info/refs request as described in http-protocol.txt and requests that v2 be used by supplying "version=2" in the Git-Protocol header.

C: Git-Protocol: version=2
C:
C: GET $GIT_URL/info/refs?service=git-upload-pack HTTP/1.0

A v2 server would reply:

   S: 200 OK
   S: <Some headers>
   S: ...
   S:
   S: 000eversion 2

   S: <capability-advertisement>

Subsequent requests are then made directly to the service $GIT_URL/git-upload-pack. (This works the same for git-receive-pack).

The goal is to have more capabilities:

There are two different types of capabilities:

  • normal capabilities, which can be used to to convey information or alter the behavior of a request, and
  • commands, which are the core actions that a client wants to perform (fetch, push, etc).

Protocol version 2 is stateless by default.
This means that all commands must only last a single round and be stateless from the perspective of the server side, unless the client has requested a capability indicating that state should be maintained by the server.

Clients MUST NOT require state management on the server side in order to function correctly.
This permits simple round-robin load-balancing on the server side, without needing to worry about state management.

Finally:

ls-refs is the command used to request a reference advertisement in v2.
Unlike the current reference advertisement, ls-refs takes in arguments which can be used to limit the refs sent from the server.

And:

fetch is the command used to fetch a packfile in v2.
It can be looked at as a modified version of the v1 fetch where the ref-advertisement is stripped out (since the ls-refs command fills that role) and the message format is tweaked to eliminate redundancies and permit easy addition of future extensions.


Since that commit (May 10th), the protocol V2 has officially been announced (May 28th) in the Google blog post "Introducing Git protocol version 2" by Brandon Williams.

In both cases:

Additional features not supported in the base command will be advertised as the value of the command in the capability advertisement in the form of a space separated list of features: "<command>=<feature 1> <feature 2>"


See also commit 5e3548e, commit ff47322, commit ecc3e53 (23 Apr 2018) by Brandon Williams (mbrandonw).
(Merged by Junio C Hamano -- gitster -- in commit 41267e9, 23 May 2018)

serve: introduce the server-option capability

Introduce the "server-option" capability to protocol version 2.
This enables future clients the ability to send server specific options in command requests when using protocol version 2.

fetch: send server options when using protocol v2

Teach fetch to optionally accept server options by specifying them on the cmdline via '-o' or '--server-option'.
These server options are sent to the remote end when performing a fetch communicating using protocol version 2.

If communicating using a protocol other than v2 the provided options are ignored and not sent to the remote end.

Same is done for git ls-remote.


And the transfer protocol v2 learned to support the partial clone seen in Dec. 2017 with Git 2.16.

See commit ba95710, commit 5459268 (03 May 2018), and commit 7cc6ed2 (02 May 2018) by Jonathan Tan (jhowtan).
(Merged by Junio C Hamano -- gitster -- in commit 54db5c0, 30 May 2018)

{fetch,upload}-pack: support filter in protocol v2

The fetch-pack/upload-pack protocol v2 was developed independently of the filter parameter (used in partial fetches), thus it did not include support for it. Add support for the filter parameter.

Like in the legacy protocol, the server advertises and supports "filter" only if uploadpack.allowfilter is configured.

Like in the legacy protocol, the client continues with a warning if "--filter" is specified, but the server does not advertise it.


Git 2.19 (Q3 2018) improves the fetch part of the git transfer protocol v2:

See commit ec06283, <a href="https://github.com/git/git/commit/d093bc7582fc60b51b42d2edf32b3ce68cd283eb" rel="nofollow


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...