Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › Developer Tools

Git vs. Mercurial for Large-Scale Monorepos: Architecture, Performance, and Choosing a Stack

By Freedom251 Team · · 12 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Neither Git nor Mercurial is automatically “better” for a huge monorepo. At hundreds of thousands or millions of files, the result depends on the complete system: filesystem monitoring, history transfer, checkout design, server architecture, caches, branching policy, and the workflow around code review. Git offers unmatched ecosystem compatibility and can scale well when those pieces are deployed deliberately. Mercurial’s modular design let Meta add extensions that changed the scaling profile of its Facebook repository. The practical decision is therefore between architectures, not two default command-line clients.

What makes a monorepo “large”?

Repository size is not one number. A source tree with 500,000 text files can stress a client differently from a tree with 100,000 files and years of binary history. Before comparing tools, measure the dimensions that affect real operations:

As an Amazon Associate I earn from qualifying purchases.

  • Working-tree file count: status, ignore checks, directory traversals, and checkout bookkeeping become more expensive as the number of paths rises.
  • History size: commit count, tree metadata, and rename or merge history determine clone, pull, log, and rebase costs.
  • Binary content: frequently revised binaries enlarge storage and make ordinary delta and transfer strategies less effective.
  • Branch and head count: every active line of development adds merge, review, and server bookkeeping; an uncontrolled number of heads can become a limit in either system.
  • Concurrent users and automation: CI fleets, code-review services, and build workers multiply server requests.
  • Server bandwidth and latency: a client that is fast on a workstation can still produce an unacceptable experience if clone, update, or fetch traffic overwhelms the central service.

These dimensions interact. A repository can have a modest file count but an enormous history, or millions of files that most developers never need in a particular workspace. A meaningful comparison uses production-shaped workloads rather than a headline file count.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What happened at Facebook, and why it matters

Meta’s Facebook repository provides the clearest published Git-versus-Mercurial comparison, but it is a historical, deployment-specific result rather than a universal benchmark. In a 2014 Meta Engineering description, Facebook reported thousands of commits per week across hundreds of thousands of files. The article contrasted that repository with the Linux kernel’s 2013 scale of 17 million lines of code and 44,000 files, noting that Facebook’s source repository was many times larger by file count.

Meta also explained why a single repository was useful: large changes could be made throughout the codebase while continuous modernization remained manageable. The engineering team evaluated extending Git, then concluded that Git’s internals would be difficult to work with for an ambitious scaling project. The decision was about extensibility and the team’s ability to operate the resulting system, not a claim that Mercurial is always faster or that Git cannot support a monorepo.

The measured improvements in Meta’s deployment

Meta integrated Watchman, a filesystem-monitoring service, with Mercurial so that status did not need to discover every unchanged path by scanning the entire tree. Meta reported that Mercurial status became more than five times faster than Git status for its repository. It also built remotefilelog, which allowed clients to obtain commit metadata while downloading file contents on demand. In the same deployment, Meta reported:

Operation Reported result Qualification
Status More than 5× faster with Watchman-integrated Mercurial Meta’s Facebook repository and environment, reported in 2014
Clone and pull 10× faster with remotefilelog Meta’s deployment result, not a general comparison of current releases
Large rebases 2× faster with remotefilelog Meta’s deployment result on its large-repository workload
Mercurial server network load More than 10× lower Reported for Meta’s remotefilelog-based architecture

The important lesson is architectural. Watchman changed the cost of discovering local changes; remotefilelog changed which file history had to be transferred. A default Git checkout and a customized Mercurial stack were not the only variables, so these figures should not be used to predict performance on your repository.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How Git behaves in a very large monorepo

Git’s main advantages are broad hosting support, mature CI and code-review integrations, familiar tooling, a large hiring pool, and interoperability with existing repositories. Git is often fast for local operations, particularly when the working set and history fit comfortably on a developer’s machine. Those advantages reduce migration risk and make it easier to connect a monorepo to external teams and services.

Default behavior can become expensive when a status operation, checkout, or clone assumes that every path and every relevant object is local. Large-monorepo programs therefore tend to combine Git with several features rather than relying on the default full-history, full-tree model.

Sparse checkout and sparse working trees

Sparse checkout lets a developer materialize only selected directories or patterns in the working tree. This reduces the number of files that editors, build tools, and local scans see. It does not by itself remove all repository history or object metadata, and changing the sparse definition can trigger checkout work. Sparse trees work best when teams can describe stable ownership or project boundaries; a codebase with constant cross-directory edits may require frequent expansion of the working set.

Partial clone and on-demand objects

Partial clone allows a client to omit some objects initially and fetch them when a command needs them. This can make bootstrap and storage requirements more manageable, particularly when the repository contains long histories or large blobs. It introduces a dependency on reliable access to the object server: commands that touch omitted data may block or fail when the client is offline or the server is unavailable. CI workers must also be configured so that on-demand fetches do not create an unexpected request storm.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Filesystem monitors

Git can use a filesystem monitor to learn which paths changed instead of repeatedly examining every file. The benefit is greatest when the tree is huge and most files are unchanged between commands. Monitor correctness and lifecycle management matter: missed events, a restarted monitor, or a network-mounted workspace can force a more expensive scan or produce confusing status results. Measure cold-start and recovery behavior, not only the fastest warm-cache run.

Object caches, alternates, and virtual workspaces

Shared object caches and local alternates can prevent every clone or CI job from downloading identical history. They require explicit storage management and isolation rules so that one job cannot corrupt or unexpectedly retain another job’s objects. A virtual filesystem can go further by presenting a large logical tree while materializing files on demand. This makes the developer’s active working set, rather than the repository’s total size, the dominant cost, but it adds a service and another failure mode.

How Mercurial addresses different scaling pressures

Mercurial’s command model is often described as simpler, and its implementation was designed around extension points. Its own documentation treats large-repository performance as several separate problems rather than one “maximum repository size.” It cites successful use of repositories with more than 100,000 files and 200,000 changesets while warning that larger histories, binaries, hundreds of thousands of files, server-side bundle generation, and branch-heavy histories need different mitigations.

Shallow clones for long histories

A shallow clone transfers only a bounded portion of history. This reduces initial transfer and local storage, but historical commands and operations that cross the shallow boundary need a policy for obtaining older changesets. It is appropriate for disposable CI workers or developers who need current code, less so for workflows that routinely inspect or rewrite deep history.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Largefiles for binary-heavy trees

Mercurial’s largefiles extension keeps large binary content out of the normal changeset exchange path and retrieves it separately. That can prevent every clone from carrying every binary revision. The trade-off is operational: binary availability, retention, backup, and offline behavior become an additional service concern. Teams should decide which binaries are mandatory for a build and whether a developer can work without the rest.

Fsmonitor for expensive status scans

The fsmonitor extension addresses the same basic pressure as a Git filesystem monitor: discovering local changes in a tree with hundreds of thousands of files. It is most valuable when file events are reliable and the monitor can recover safely after sleep, reboot, or workspace relocation.

Clone bundles for server efficiency

Generating a complete clone bundle on demand can consume substantial server CPU and disk bandwidth. Clonebundles let a server advertise pre-generated bundles so clients can obtain bulk data from an appropriate location before requesting incremental changes. Bundle production, invalidation, distribution, and access control still need to be operated; the feature shifts work rather than eliminating it.

Generaldelta for branch-heavy histories

Generaldelta changes how revisions are delta-compressed so storage does not depend as heavily on a single linear path. Mercurial documents it as a response to branchy histories that can otherwise waste space. It does not replace a branching policy: a repository with a very large number of active heads still incurs merge, review, and metadata costs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

History transfer and checkout: the decisive performance differences

For a large monorepo, “clone speed” is not a single metric. Separate the work into the following stages:

Stage Questions to measure Typical levers
Bootstrap How long until a developer can edit and build a small project? How much data is transferred? Shallow or partial history, clone bundles, object caches, remotefilelog-style on-demand content
Working-tree materialization How long to create or change the visible tree? Sparse checkout, virtual filesystem, filesystem monitor, workspace-local caches
Update or pull How much metadata and file content arrive for an ordinary change? On-demand file history, server-side caching, incremental bundles
History-heavy work What happens during a large rebase, merge, blame, or cross-project refactor? Local object availability, delta strategy, head count, server round trips

On-demand designs improve the common case when a developer touches only a small portion of the tree. They can make an offline or degraded-service incident more disruptive because omitted history or file content is unavailable locally. A full local clone has higher setup cost but preserves more offline capability. The right choice depends on whether your organization values minimal workstation footprint or uninterrupted local operation.

Modern stacks blur the Git-versus-Mercurial boundary

Meta’s later tooling illustrates why the client name is an incomplete description of a monorepo system. Meta describes Sapling as a Git-compatible client derived in part from Mercurial concepts, paired with Mononoke as a scalable server and EdenFS as a virtual filesystem. Meta states that this compatible stack is intended to serve tens of millions of files, tens of millions of commits, and tens of millions of branches, and that it is used primarily for the company’s large monolithic repository.

The design goal is to make operations scale with the files a developer is using rather than with the total repository size. Specialized metadata services, caches, and virtualized workspaces can preserve familiar version-control semantics while moving repository-scale work away from a single local checkout. Other organizations may assemble a different combination, but the pattern is widely applicable: evaluate the client, server, storage, workspace layer, and CI behavior together.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Branching policy can outweigh the client choice

A monorepo’s head topology is a first-class scaling axis. Trunk-based development, short-lived branches, stacked changes, merge queues, and review-based landing each impose different costs. A team that creates a head for every experiment may overload merge and review systems even if file operations are fast. Conversely, an aggressive single-trunk policy can require dependable presubmit testing and fast rollback procedures.

Meta has described large-monorepo branching as a trade-off between scalability and developer experience. Benefits include unified dependency management and large-scale refactoring, but they require workflow rules that keep integration predictable. Mozilla documentation warns that both Mercurial and Git have known scaling problems as the number of repository heads approaches infinity. Head cleanup, branch lifetime limits, and explicit ownership of long-running release lines should therefore be part of the architecture review.

Questions to ask about heads and merges

  • How many active heads exist during a normal week, and how many appear during a release?
  • Are changes landed directly to a trunk, through a merge queue, or by merging long-lived branches?
  • Does code review represent one commit, a stack of commits, or a merge result?
  • Can developers rebase or update while offline, or does the workflow require a central service?
  • What automated action removes abandoned heads and stale review branches?
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Which should you choose?

Choose Git when ecosystem compatibility is the dominant constraint

Git is the pragmatic choice when your organization depends on existing hosting, CI, IDE, review, deployment, and automation integrations; hires primarily from the Git ecosystem; or must interoperate with many external repositories. Plan to deploy the scaling features that your measurements justify: sparse or virtual workspaces, partial history, filesystem monitoring, object caching, and server-side support for high concurrency. Treat those services as part of the product, with ownership, monitoring, upgrades, and incident procedures.

Choose Mercurial when modularity and existing expertise fit better

Mercurial is attractive when the team values its command model and extension architecture, already operates Mercurial infrastructure, or needs to tailor history and workspace behavior deeply. Meta’s experience demonstrates that extensions such as Watchman integration and remotefilelog can materially change performance. You still need to operate the associated monitors, metadata services, storage, and caches, and you must verify integration with the tools your developers and CI use.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose a compatible specialized stack for extreme scale

At tens of millions of files or commits, a conventional full local checkout may be the wrong abstraction regardless of client. A Git-compatible client with a scalable server and virtual filesystem, as illustrated by Sapling, Mononoke, and EdenFS, can preserve familiar workflows while limiting local work to the active slice of the repository. This path has the largest systems footprint and should be justified by measurements showing that simpler sparse or partial approaches are insufficient.

How to run a fair evaluation

Do not benchmark empty repositories or synthetic trees alone. Build a representative copy with the same file-type mix, history shape, binary revisions, generated files, branch topology, and review workflow that production will have. Compare complete stacks, including server configuration and workspace layer.

  1. Define target workloads. Include initial bootstrap, warm and cold status, checkout or update, diff, commit, log and blame, pull or fetch, branch creation, rebase or stack update, merge, and a large cross-project refactor.
  2. Use realistic environments. Test developer laptops, CI workers, remote or network-mounted workspaces if they are supported, and the slowest network regions your team serves.
  3. Record both warm and cold behavior. Repeat tests after caches are populated, then clear filesystem, object, and server caches. Report the distribution, not just the fastest run.
  4. Measure resource costs. Capture client CPU, memory, disk use, server CPU, storage I/O, network bytes, request counts, and concurrency under a realistic number of users and jobs.
  5. Test failure and offline modes. Disconnect the central service, stop the filesystem monitor, expire a cache, and interrupt a partial transfer. Document which commands continue locally and how recovery works.
  6. Vary head count. Repeat merge, rebase, update, and review-queue tests with the number of active heads expected during ordinary development and releases.
  7. Set acceptance thresholds. Define maximum bootstrap time, interactive status latency, update time, CI queue impact, workstation storage, and server bandwidth before choosing a tool.

Common mistakes and their remedies

Comparing default clients instead of deployed systems

A full Git clone against an on-demand Mercurial deployment answers a narrow historical question, not the one your team faces. Enable equivalent monitoring, sparse or virtual workspaces, history depth, caching, and server capacity before drawing conclusions.

Optimizing only the first clone

A fast bootstrap does not guarantee responsive status, checkout, merge, or refactor operations. Track the entire developer day and the CI lifecycle, including repeated updates and large changes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Ignoring offline behavior

Partial history, remote file content, and virtual filesystems reduce local storage but increase dependence on central services. Decide which tasks must work during an outage or on an airplane, and prefetch or materialize the necessary data for those tasks.

Letting branch heads grow without a policy

No filesystem monitor can compensate for merge queues and metadata overwhelmed by an uncontrolled head count. Establish branch lifetime, landing, and cleanup rules alongside repository tooling.

Underestimating operational ownership

Monorepo extensions are production infrastructure. Assign owners for bundle generation, object or metadata storage, filesystem monitors, virtual workspace services, cache invalidation, backups, and migration procedures. Include their failure modes in on-call practice.

Bottom line

For a huge monorepo, choose the stack that meets your measured workloads and operational constraints. Git usually wins on ecosystem reach and staffing flexibility, provided you add the workspace, history, monitoring, caching, and server architecture needed at scale. Mercurial can be an excellent foundation when its modularity and your team’s expertise enable extensions such as filesystem monitoring and on-demand file history; Meta’s 2014 results show how substantial those changes can be in one environment. At the extreme end, a specialized client-server-virtual-filesystem system may matter more than whether the command name is Git or Mercurial. Benchmark the complete architecture, control the number of heads, and make offline and failure behavior explicit before committing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Developer ToolsGitMercurialmonorepossoftware architectureVersion Control

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.