Deep dive into Git's wire protocol

schacon1 pts0 comments

Git Wire Protocol v2: A Deep Dive - Scott Chacon<br>scottchacon.com ← all posts

⧓ gitbutler.com — What I'm building now: a better version control system

Git Wire Protocol v2: A Deep Dive<br>July 29, 2026 · today · 8 min read<br>Recently, I’ve been messing about with Git server stuff for some experimental work for GitButler. In doing that, one of the things that I’ve been digging into is the bundle-uri and packfile-uri capabilities.

Looking more into it made me realize that I’m not as familiar with how Git’s server works these days as I thought I was. Specifically, I had never really learned about Git’s new (8 years old) “v2” server protocol, which is what those capabilities are built on. So I did a bit of a deep dive.

Smart HTTP, First Edition

When I published the first version of the Pro Git book in August of 2009, Git barely had HTTP support at all. What it had then is now referred to as the “dumb” protocol, just serving static files directly over HTTP.

In December of 2009, Git 1.6.6 landed with the first “smart” HTTP protocol - a CGI script you could load into Apache or whatever to handle ref advertisement and object negotiation via the same git-upload-pack and git-receive-pack binaries that SSH runs via git-shell for communication.

That first “smart” HTTP support landed as part of a huge 28-patch series from Shawn Pearce — the origin of git-http-backend and the smart client and server we still use:

Shawn O. Pearce · Oct 30, 2009<br>lore.kernel.org · 3 messages

Smart HTTP transport Hopefully the final spin of the smart HTTP series. I think we are<br>down to bike shedding, which I take it means folks are otherwise<br>reasonably happy with the code.<br>Read the first message →<br>✉Git-aware CGI to provide dumb HTTP transport (v5 13/28) 2f4038ab33<br>✉Smart fetch and push over HTTP: server side (v5 15/28) 556cfa3b6d<br>✉Discover refs via smart HTTP server when available (v5 21/28) 97cc7bc45c

Since this landed after Pro Git (ed 1) was published, one of the bigger updates in the second edition of the book was to describe HTTP as a first-class protocol to use. I actually wrote a blog post here in 2010 outlining the new “smart” HTTP.

HTTP Protocol V2

I published the second edition of Pro Git in November of 2014 updated with these changes, and a few years later the HTTP transport got smarter again with the v2 protocol.

Since I wasn’t as heavily into Git stuff for a bit, I sort of missed what this meant and why it was done, so I’ve recently dug into it. If you’re curious how Git’s modern HTTP protocol works, this is the blog post for you.

Why a New Protocol?

The first version of the smart protocol would basically do a dump of every reference when you first connected, so the client could determine what objects it had or needed and continue to the negotiation or object push.

That’s fine for most projects, but when your repository has hundreds of thousands of refs, it becomes a lot of data to send over the wire every time you want to do anything at all. So one of the first things the new protocol could do was filter the refs advertised with the ls-refs command.

GitLab's references The gitlab project has over 800k<br>references. A full git ls-remote on that repository takes almost 9 seconds<br>and sends 58M over the wire. Imagine having to run that before even a tiny<br>incremental push or fetch.

Another problem was capabilities advertisement. The first version sort of shoehorned them in to the first reference line, hidden behind a NUL byte, which means a server could never advertise more than the size of a pkt-line.

Finally, instead of multiple service names, in v2, multiple commands can be supported by a single service. This means that instead of adding new commands by adding new http endpoints, the git-upload-pack service can now be asked to do lots of different things other than producing packfiles (like listing filtered references, for example).

To lay the foundation to address these issues, Brandon Williams of Google introduced git-serve in March 2018, along with the first two capabilities, ls-refs and fetch.

ed10cb95 serve: introduce git-serve @bmwill · Mar 15, 2018 The introduction of the v2 capable server

It finally became the default protocol for the client in Git 2.29, released in October 2020.

Anatomy of a Git HTTP conversation

OK, so what did an HTTP conversation look like with the first protocol and what does it look like with v2? Let’s walk through a clone of a small repository to see the difference.

The First Protocol

Originally, the “Smart” HTTP conversation went something like this.

For a clone, the client would make two HTTP round trips. One to figure out what the reference tips (branches) are. The second to tell the server what it wanted so the server could generate a packfile of just the data needed.

Let’s look at each HTTP request in a bit of detail. The first roundtrip is a GET request that asks for references and server capabilities.

Roundtrip 1 · GET...

http protocol first server smart wire

Related Articles