objgit rebuilds Git's packfile format for object storage

The author is building objgit, an open-source Git server backed by object storage. The first approach used a filesystem shim on top of object storage so Git would see something that looked like a normal disk, but that fell apart on real-world-sized repositories, so the design shifted to storing Git's own objects directly as objects in the storage backend (Tigris). The remaining bottleneck turned out to be Git's packfile format itself. Git bundles many small objects into a single packfile with an index, and on local disk it memory-maps that file so the kernel can serve reads straight from cached pages, which the author estimates at about 10 nanoseconds. A network round trip to object storage costs at least 10 milliseconds, roughly a million times slower by this comparison, so replaying Git's normal disk access pattern over a network is a nonstarter. Fetching objects one at a time makes the problem concrete: a copy of the Linux kernel repository reports 11,827,138 objects packed into roughly a 3.4Gi packfile, and at an assumed 10 milliseconds per GetObject call, pulling each object out individually would take over an hour, versus a single request for the whole packfile today. HTTP Range requests looked like the fix, since they can pull one byte range out of a larger object, but Git's packfile index only records where each object starts and its decompressed size, not its compressed size on disk, so there is not enough information in the index alone to construct a correct Range request for a single object. A second friction point is that object storage's GetObject/PutObject model will not let a client read an object before its write has finished, unlike the local write-then-reread pattern Git normally uses to compute hashes. Facing these two problems, the author designed a new packfile format built specifically for object storage, describing it as a columnar store, and drew an analogy to CD/DVD cue sheets, which store separate seek information alongside a disc image so a decoder can jump straight to a track without reading the whole disc. By the author's account the new format "worked surprisingly well" on production-sized repositories and needs no changes on the Git client side. The post's technical walkthrough of the new format's internal layout is not included in the text made available for this summary, which ends partway through the author's explanation of why building a custom format was justified despite Git being the kind of distributed system where every clone carries the full history.
Key facts
- Git's packfile index records where an object starts and its decompressed size, but not its compressed size on disk, so there is not enough information to build an HTTP Range request for a single object inside a packfile.
- A copy of the Linux kernel repository packs 11,827,138 objects into one packfile of about 3.4Gi; fetching them individually at an assumed 10 milliseconds per GetObject call would take over an hour.
- The author models a cached local filesystem read at 10 nanoseconds versus a network round trip at 10 milliseconds minimum, a gap of about a million times, as the reason Git's mmap-based packfile design does not translate to object storage.
- Object storage's GetObject/PutObject model will not let a client read an object before its write has finished, breaking the write-then-reread pattern Git uses locally to compute hashes.
- The resulting new packfile format is a columnar, object-storage-native design, inspired by CD/DVD cue sheets, and per the author works well on production-sized repositories without any change on the Git client side.
Why it matters
Git's on-disk formats assume a local filesystem: memory-mapped packfiles, cheap re-reads, and a write-then-hash pattern that all rely on disk latencies measured in nanoseconds. Object storage offers none of that, and the author's numbers make the mismatch concrete: individually fetching the Linux kernel's nearly 12 million packed objects over a network would take over an hour, against a single request for the whole packfile today. The fix is not a workaround bolted onto Git's existing packfile index, which the author shows lacks the compressed-size information needed for range requests, but a new packfile format designed around object storage's constraints from the start.
Who it affects
This is aimed at people building Git hosting or Git-compatible services on top of object storage rather than local disks, including the author's own objgit project. It does not change anything for a typical Git user running the standard client against a normal filesystem-backed server.
How to use it
objgit is described as an open-source project; the text gives no version number, release date, pricing, or instructions for adopting the new packfile format, so none of that is stated here.
How solid is it
The evidence given is the author's own account of building and testing objgit, including a live example from his own project checkout (756 objects, 448 packed) and a worked estimate for the Linux kernel repository, plus the qualitative claim that the new format "worked surprisingly well" on production-sized repositories. The text does not include an independent benchmark, and the portion made available here breaks off before the author lays out the internal design of the new format in detail.
Risks and caveats
The account is single-author and self-reported, with no outside verification of the performance claims. The text does not say whether the new packfile format has shipped, been merged upstream anywhere, or remains experimental, and it does not name any of the other companies the author alludes to as shipping a Git product recently. The design is also built around Tigris's specific object storage behavior, so how it generalizes to other object storage backends is not addressed.
“Git packfiles were designed for mmap and local disk, so pulling one object out of a bucket means guessing at a byte range.”
— the author, on the Tigris blog