A Git Forge Without a Center
In 2007, Linus Torvalds, who needs no introduction, said: _“If you’re not distributed, you’re not worth using, it’s that simple.”_ Before distributed version control went mainstream, the repository and its history lived on the server. Git changed that. Developers could create commits and branches, or rewrite history, locally, and reconcile later when needed.
The protocol supported distribution and even decentralization, but forges never lived up to it. Git distributed the repository to the client, and forges centralized the server side again and again. And for decades, centralization worked for human-paced traffic.
Agents changed this setup. They work in disposable workspaces. Developers who run agents locally already have a copy of the repository and might use Git worktrees to share storage. But a new cloud worker starts with nothing and has to clone the repository. These workers run wherever compute capacity is available, but every clone operation hits the central storage. Multiply that by every agent task in every repository at every company in the world, and the problem becomes obvious. The workload is distributed, but the infrastructure is not.
Yet even today, with demand for new forges at a fever pitch, many have forgotten Torvalds’ advice. They treat being distributed as a hindrance rather than an advantage, because distribution is hard, and some are going as far to replace Git entirely. For example, Anthropic recently built Scion, an impressive internal replacement for Git, while conceding that it is _“by no means a suitable replacement for git for general use.”_ The truth is: A Git server _can_ handle agent-scale workloads of tens of thousands of merges a day while staying compatible with Git, but not if it is in a centralized model. Shying away from Git’s original promise of distribution will only worsen the very bottleneck we now face in software development.
Scaling for the agent era requires us to build an infrastructure where repositories can live in more than one place, near the machines accessing them. That makes the current moment a storage-architecture problem. The extent to which read operations can be distributed across a system, and the volume of concurrent requests it can handle, are determined by how a host stores a repository, how many copies it keeps, where those copies live, and how they are synchronized before a change becomes visible.
Yesterday, we launched Entire, the first Git forge for agent-human collaboration. Entire is a rebuilt forge which is compatible with Git. Our source control server, internally named EntireDB, keeps full copies of the repositories in the regions where the agents are actually running. Clone operations are served from regional copies rather than piling into a single origin. Each copy is a complete repository and can serve reads independently. Due to this architecture, Entire is the fastest Git forge ever created. According to our open-source benchmarks, pushes are up to 89x faster than GitHub, Cursor Origin and every major Git forge in production today. Here’s how it works and how it compares with other forges.
Pushes per second Up to 89× faster
!Image 1Entire 418
!Image 2Cursor 65
!Image 3Pierre 15
!Image 4GitLab 10
!Image 5GitHub 4.7
How Other Git Hosts Store Repositories
To explain what is different about our architecture it helps to contrast it with two designs from which Entire departs.
Spokes is GitHub’s established design for replicated Git storage. By design, GitHub Spokes keeps at least three copies of each repository. It streams writes to the replicas and accepts a write only when a strict majority, and always at least two replicas, commit it with the same resulting repository state. Spokes works at the packfile level rather than reinventing Git. It keeps repositories on fast local disks and ensures that reads are served only from up-to-date replicas. Replicas that deviate from the majority are marked as “unhealthy” until repaired.
This design limits the number of voting replicas that can participate in write operations. Committing a push requires coordination with a majority of these replicas. Adding more voting replicas increases coordination overhead. Spokes can also use non-voting replicas for geographically local reads without putting them on the voting path. This limits the size and geographic spread of the voting set, but not the total number of read replicas. Spokes can manage non-voting replicas without including them in the write quorum. However, these replicas must still be synchronized and tracked, and excluded from read operations when they are not up to date.
GitHub Spokes At least three copies of each repository
The client sends its pack to the Spokes Proxy, which streams it to every replica. 1. The client sends its pack to the Spokes Proxy, which streams it to every replica. 2. Each replica stages the incoming pack before applying it to its own copy of main. 3. All three replicas report back — a strict majority quorum is reached on 3f2a. 4. The proxy acknowledges the push, and the replicas settle on the new commit. 5. A second client fetches main — still pointing at the old commit, a91e. 6. The proxy chooses a current replica to serve the read — replica 02, up to date. 7. The chosen replica returns its ref and pack. The client's fetch catches up to 3f2a.
A more recent design worth inspecting is Cursor’s Continuity, described in the blog post, “Git at any scale.” Continuity’s key architectural distinction is to take the agreement out of the replica set and delegate it to S3. The write-ahead log (WAL) in S3-compatible storage becomes the source of truth, and on-disk repositories become warm caches. A client’s push becomes durable once its entry is in S3, but is visible only once the ref transaction is prepared against a single local repository and the entry is published via an atomic compare-and-swap on the WAL index object in S3.
Since a push affects only a single local repository rather than a quorum, and S3 index updates are batched, Cursor reports that this allows Continuity to accept pushes as quickly as its local disk allows. The trade-off here is that S3 moves onto the read path. Every fetch or clone operation needs to perform a conditional GET to S3 to check whether it is up to date with the source of truth.
In exchange, replicas become disposable. Since a repository can be reconstructed from the WAL on any node, the loss of a replica costs a rebuild, and no quorum reconfiguration is required.
Cursor Continuity The write-ahead log becomes the source of truth
01 / 06
Node A takes the pack and streams the WAL object toward S3.
Inside a Cell: How Entire Stores a Repository
In contrast to the above designs, for EntireDB, we leaned into the distributed nature of Git from the beginning. EntireDB keeps the durable source of truth inside the cell that serves the repository. A cell consists of one PostgreSQL database that holds refs and a set of EntireDB nodes which hold loose objects and packfiles. A repository is assigned to one cell. PostgreSQL provides the ordered state that is needed to serialize competing updates to the same ref.
To understand why we split our storage across disk and a relational database, let’s look at the Git transfer protocol.
A Git push has two logical parts: a packfile containing the new objects (commits, trees, and blobs), and a ref update that makes those objects visible by moving a reference (branch or tag) to a new commit. Refs are mutable, so storing them in a database made sense to us. Every ref update is a compare-and-swap against the expected previous state. Objects are immutable and content-addressed, so nodes can receive them concurrently.
This split means we have to run PostgreSQL alongside the storage nodes. We accept this trade-off because storing each ref in its own row lets us update references independently.
The next question is how EntireDB chooses which nodes receive objects and packfiles. Git operations need to walk a directed acyclic graph (DAG) one object at a time. EntireDB places objects by repository ID, so all objects for a repository are assigned the same set of nodes, the repository’s providers. Commits, trees, and blobs needed for a graph walk are therefore usually available on one provider.
Clients access EntireDB via a Git remote helper, a small client-side program invoked by Git for EntireDB remotes. For pushes, fetches, and clones, the helper contacts a discovery endpoint to receive the repository’s refs and its providers. It then selects one provider. The Git transfer then happens directly between the client and that provider. The remote helper automatically handles client-side failover and caches the provider list for a day, so subsequent Git operations do not need the discovery mechanism.
A Push: First the Objects, Then the Branch
A push to an EntireDB node takes place in stages.
1. The provider that receives the push from a client acts as the coordinator. It streams the packfile concurrently to other providers while it stages its own copy. 2. The objects land in a staging area on each provider that is invisible to readers. At least two providers in distinct availability zones must confirm that they received the staged pack. Otherwise, the push aborts. 3. As soon as one provider has staged the pack, that provider checks all objects within the pack and confirms that every object the proposed refs reach is present. 4. Once validation succeeds and staging quorum is met, the coordinator asks each provider that staged the pack to promote it, making the objects part of the repository’s durable object store. 5. It then confirms that at least two providers in separate availability zones completed the promotion. This must be done because a provider may have been stopped between staging and promoting. 6. Only if this check passes, it sends the compare-and-swap ref update to PostgreSQL. The push becomes visible once this update succeeds.
Spokes, Continuity, and EntireDB all ensure that objects are durably stored before publishing the updated refs. The difference lies in where this durable storage takes place and which component is responsible for handling the coordination.
In Spokes, repository replicas participate in push transactions. In Continuity, S3 stores the durable log. In EntireDB, the serving nodes store the content-addressed objects while PostgreSQL handles ref updates. In other words, EntireDB resembles Spokes in storing content-addressed objects on the nodes that serve it, but resembles Continuity in keeping storage nodes out of the ref transaction.
A Fetch: Everything Served from Within the Cell
In a push operation, objects are distributed across several nodes, whereas a fetch typically involves only a single node. The selected node reads the repository’s refs from PostgreSQL, generates the requested packfile using objects stored on its local disk, and streams it directly to the client. If a required object is missing, the node retrieves it from another assigned node. Nothing outside the cell is accessed to serve the repository.
EntireDB cell First the objects, then the branch
01 / 10 Fan out the pack
Node A streams pack 3f2a to every node in the cell.
Where Entire Keeps a Cell: Regions and Placement
We currently operate cells in the US, Europe, India, and Australia. Those are registered in our global control plane which holds the repository’s placement. A region consists of one or more cells and provides a data-residency boundary. Unless users explicitly replicate repositories to other regions, repositories remain in their creation region.
Most repositories on Entire today mirror a repository from GitHub and accept pushes through EntireDB. A push to a mirror stores the objects in the cell, forwards the push to GitHub, and updates the local refs only if GitHub accepts the push. Branches under `refs/heads/entire/unmirrored/` are an exception. They skip the forward entirely, and a GitHub sync does not affect them in either direction.
We also support repositories that are not mirrored from GitHub. Such a repository is located in one primary cell that acts as the upstream for every cell that mirrors it. While other regional placements can receive pushes, they forward them entirely to the home cell and only update their local refs if the home cell accepts the operation. Fetches and clones are served by any cell that mirrors the repository.
A ref change in the home cell triggers the synchronization of the complete ref state to every mirror placement via the git protocol. The underlying pipeline is not new: it has already been in production for months for GitHub mirrors. The synchronization code is git-sync, the open-source project we developed for this use case.
Mirror propagation Fetches and clones are served by any cell
01 / 05 Reads stay local
A fetch for main is served from the AU mirror’s own copy — no round trip to the home cell.
Tradeoffs and Limits
Within an EntireDB cell, refs are strongly consistent as every node reads them from the same PostgreSQL database. Objects, unlike refs, replicate asynchronously. EntireDB can acknowledge a push once two nodes in different availability zones hold the objects and the ref update succeeds. The remaining assigned nodes catch up asynchronously if needed. Since each node immediately sees the new ref, it can advertise it even before the corresponding objects are stored locally. During this period, the node retrieves missing objects from another node within the cell.
Replication between cells is asynchronous. A mirror placement may lag behind the upstream it syncs from, while ref changes propagate. Within one cell, EntireDB provides read-your-writes consistency. Supporting more than one writable cell would require a conflict-resolution model, which we do not currently provide.
Testing the Boundary
This architecture required us to implement a Git-compatible server we built using go-git, which has excellent interfaces for implementing Git servers. Owning the boundary between Git’s protocol and our distributed storage also made its correctness our responsibility.
We test every change to EntireDB using Antithesis’ deterministic simulation testing platform. The simulator partitions the network, pauses and kills nodes, skews clocks, while our workload exercises operations including our node deployment process. During the run we check invariants that must always hold. For example, a node advertising a ref must either deliver the complete object graph or return an error. It must never return partial data. That test found a case where a fetch could return a half-written packfile, and we fixed it.
Antithesis Deterministic simulation testing
Something Entirely New
For twenty years the limiting factor was how fast code could be written. Today, the new limitation is increasingly how fast code can reach the agents that need it. Torvalds’ belief in distribution has aged well, and it has only changed target: he was describing version control systems, and the same test now applies to the forges built on top of them. A world where billions of agents are cloning and committing will not be served by a bigger center. It will be served by a distributed Git network that brings repositories closer to the agents that need them.
**We will open source EntireDB in the coming months. Contact us at support@entire.io if you are interested in early access and contributing to it.**