Git started life as version control software developed to manage the source code for the Linux kernel. It's since become the default, go-to tool for managing source codebases for just about every open source project—and many closed-source ones, too.
For all its popularity, Git also draws deep and legitimate complaints. It has a complex model for how code is staged, maybe too complex for its own good. Its command set can be confusing. Unfortunately, GUIs and front-ends just mask the underlying complexity rather than solving the underlying problem. Git also does not do well with certain kinds of files that are tracked in open source projects, like large binaries and complex data structures.
If any of these issues trouble you, you might be curious about feasible alternatives to Git. They do exist, and many of them prosper in their own spaces because they offer features Git doesn't have. In this article, we'll look at three of the biggest Git alternatives: Fossil, Mercurial, and Subversion. We'll cover their features and use cases and the projects they're being used in right now.
Fossil
D. Richard Hipp is best known as the creator of SQLite, the embeddable open source database system that is one of the most widely used pieces of software in the world. But Hipp does not use Git for source control on the SQLite project. Instead, he uses Fossil, a source control system he created specifically to aid SQLite's development.
Fossil's biggest difference from Git is that it's an all-in-one product. Git only handles tracking and annotating changes across a codebase by way of a virtual filesystem. Fossil is more akin to something like Bitbucket—it's a self-hosting system that not only tracks changes but integrates ticketing and bug tracking, wikis, documentation, and live discussion for a project. All of this is backed by the SQLite database, and (like SQLite itself) run from a single, standalone executable with a footprint of approximately 8MB.
Fossil uses a similar data structure to Git, but where Git uses the filesystem itself to store changes, Fossil keeps everything in an SQLite database. Queries about changes, such as examining all the changes to a given file over time, or detailed graphs about a project's progress, can be computed quickly, as they amount to SQL queries.
The design and behavioral differences in Fossil make it, according to Hipp, more suited to smaller, more intimate teams, like the ones that work on SQLite and Fossil itself. Fossil can still work in a decentralized fashion, but most remote changes are automatically synced with a main repository, instead of being separately developed over time and then reconciled (what Hipp calls the "sync over push" philosophy). The Tcl/Tk project uses Fossil, as do a few other Tcl-related projects.
Hipp provides detailed notes on moving between Git and Fossil, or synchronizing a project between both systems. Note that Fossil-specific features like a project's wiki don't port to Git, at least not automatically.
Mercurial
In 2005, the proprietary source control system BitKeeper revoked its free license for the Linux kernel. Two replacements sprung up in BitKeeper's wake. One was Git, used for the Linux kernel (and later, many other things). The other was Mercurial, which didn't end up being used by the Linux kernel project, but is still in use by developers working at Facebook, Mozilla, the W3C, and the PyPy project.
Conceptually, Mercurial and Git work the same way. They both use a graph of the changes made to a codebase, and any one change can have many children. But the core Mercurial command set for common use cases is smaller and easier to master—it's six or seven commands compared to the dozen-plus-one uses in most Git scenarios.
One key difference with Git is how branches in a source tree work. When you change branches in Git, your current directory is rewritten to reflect the contents of the branch. In Mercurial, there are a few different strategies for branching:
- You can clone the repository into another directory and work on that as a branch (easy to change branches but slow to make them).
- You can bookmark different points in a changeset and use them as the basis for changes, which closely resembles Git's own behavior.
- You can use a "named branch," where the name is made a permanent part of the changeset—useful in that the name is reflected in every future change to that branch, but it can create clutter.
- You can create anonymous, unnamed branches, which are convenient for fast changes but can get confusing if you don't properly explain what you've done in your change notes.
If you want to change the way Git behaves, you generally use other standalone programs, as per the Linux toolchain's "every program does one thing" philosophy. By contrast, Mercurial offers an extension mechanism, so that third-party code can be integrated directly into Mercurial and expand its functionality. Mercurial comes bundled with a slew of extensions, enabling everything from making change comparisons with external utilities to wiping everything in a given directory that's not actively changed by Mercurial. Perhaps the most outwardly useful feature is the ability to sync a Mercurial repository to a Git repository, which is great if you're transitioning a codebase from one to the other.
Subversion
The Apache Foundation's Subversion project—also known as SVN—originally emerged in 2000. Its initial 1.0 release, in 2004, slightly predated Git. Apache, FreeBSD, and SourceForge are some of Subversion's best-known users. The GCC project used it until 2019 but has since migrated to Git.
SVN's chief difference from Git is that it's centralized, meaning the repository is stored in a single, fixed location. Contributors typically don't make local copies of the codebase but work on branches of the code in the centralized copy. An adminstrator can set highly granular access controls on a Subversion repository, so contributions don't have to be sorted out manually.
The centralized nature of SVN is both a boon and a burden. It's a burden in that if anything ever happens to the central repository, you'd better have a good backup plan. Having every developer keep a copy of the code makes projects far more resilient to dead hard drives (or vengeful sysadmins). It also makes it difficult to test the entire codebase at once. And it also means branches of the code are handled less elegantly—they're basically physical directories with discrete copies of the code, instead of Git's virtual filesystem model.
But the centralized layout is a boon in that it makes SVN's conceptual model far simpler, and in turn makes SVN easier to work with overall. There are fewer steps needed to know about when working with a codebase, even if those individual steps have more requirements. Also, SVN handles large binary files better, since it uses a differencing algorithm well-suited to such files.
Another chief difference stems from SVN's centrality. The history of a repository is immutable. Git allows a repository's history to be modified retroactively, but SVN does not. It's a single source of truth for a project, and that's crucial if tight control over the source matters.
GitHub itself supported Subversion repositories for some time, but will phase out support as of January 2024. (GitLab and Bitbucket do not support Subversion repositories; to use them, you would need to convert a repository to Git manually.)
Conclusion
Fossil provides an all-in-one experience akin to a code-hosting platform in a box, complete with ticketing and discussion, whereas Git focuses exclusively on change tracking via a Unix-philosophy tool collection. Mercurial's extension mechanism makes it natively modifiable; Git's behaviors would be modified with external tools. And Subversion's centralization provides a simpler conceptual model and tighter control over the source, versus Git's complex concepts and decentralized file handling.