Introduction

SQLite does not use the [https://git-scm.org|Git] version control system. SQLite uses [https://fossil-scm.org/|Fossil] instead, which is a version control system that was specifically designed and written to support SQLite.

People sometimes ask why SQLite does not use the [https://git-scm.org|Git] version control system like everybody else. This article attempts to answer that question. Also, in section 3, this article provides hints to Git users about how they can easily access the SQLite source code.

This article is not a comparison between Fossil and Git. See [https://fossil-scm.org/fossil/doc/trunk/www/fossil-v-git.wiki] for a comparison of the two systems.

Edits

This article has been revised multiple times in an attempt to improve clarity, address concerns and misgivings, and to fix errors identified on [https://news.ycombinator.com/item?id=16806114|Hacker News], [https://www.reddit.com/r/programming/comments/8c2niw/why_sqlite_does_not_use_git/|Reddit] and [https://lobste.rs/s/slcntl/why_sqlite_does_not_use_git|Lobsters]. The complete edit history can be seen at [https://sqlite.org/docsrc/finfo/pages/whynotgit.in].

A Few Reasons Why SQLite Does Not Use Git

One could summarize the reason why SQLite does not use Git in a single sentence: The lead SQLite developer finds Git to be unpalatable. If you like Git and want to use it, that's great. I do not like Git and would rather use something that I think is better.

The following are a few of the reasons why I do not like Git:

Git makes it difficult to find successors (descendents) of a check-in

Git allows you to go backwards in time easily. Given the latest check-in on a branch, Git lets you see all the ancestors of that check-in. But Git makes it difficult to move in the other direction. Given some historical check-in, it is quite challenging in Git to find out what came next. It can be done, but it is sufficiently difficult that people rarely do it. Common interfaces for Git, such as GitHub, do not support the ability.

It is not impossible to find the descendents of a check-in in Git. It is merely difficult. For example, there is a [https://stackoverflow.com/questions/27960605/find-all-the-direct-descendants-of-a-given-commit#27962018|stackoverflow page] showing the command sequence for finding the descendents of a check-in in unix: git rev-list --all --parents | grep "^.\{40\}.*.*" | awk '{print $1}'

This command sequence is a lot to memorize and type. (One would want to create a bash alias or short shell script if it were used frequently.) Furthermore, it is not quite the same thing. The command above gives one a list of descendents without showing the branching structure, which is important for understanding what happened. In contrast, Fossil offers displays such as [https://sqlite.org/src/timeline?d=8a439a6dda390d74&n=15], which is a tremendous help in analyzing the aftermath of historical changes.

And it is not really about just finding the descendents of a check-in from time to time. The fact that descendents are readily available in Fossil means that the information pervades the web pages provided by Fossil. One example: Every Fossil check-in information page ([https://www.sqlite.org/src/info/ec7addc87f97bcff|example]) shows a small "Context" graph of the immediate predecessor and successors to that check-in. This helps the user maintain better situational awareness, and it provides useful capabilities, such as the ability click forward to the next check-in in sequence. Another example: Fossil easily shows the context around a specific check-in ([https://www.sqlite.org/src/timeline?c=2018-03-16&n=10|example]) which again helps to promote situational awareness and a deeper understanding of what is happening in the code.

All of the above is possible with Git, given the right extensions and tools and using the right commands. But it is not easy to do, and so it rarely gets done. Consequently, developers have less awareness of what is happening in the code.

The mental model for Git is needlessly complex

The complexity of Git distracts attention from the software under development. A user of Git needs to keep all of the following in mind:

  1. The working directory
  2. The "index" or staging area
  3. The local head
  4. The local copy of the remote head
  5. The actual remote head

Git contains commands (or options on commands) for moving and comparing content between all of these locations.

In contrast, Fossil users only need to think about their working directory and the check-in they are working on. That is 60% less distraction. Every developer has a finite number of brain-cycles. Fossil requires fewer brain-cycles to operate, thus freeing up intellectual resources to focus on the software under development.

One user of both Git and Fossil [https://news.ycombinator.com/item?id=16806955|writes in HN]:

Fossil gives me peace of mind that I have everything ... synced to the server with a single command.... I never get this peace of mind with git.

Git does not track historical branch names

Git keeps the complete DAG of the check-in sequence. But branch tags are local information that is not synced and not retained once a branch closes. This makes review of historical branches tedious.

As an example, consider display of a single historical branch of SQLite as rendered by GitHub and by Fossil:

The Fossil view clearly shows that the branch was eventually merged back into trunk. It shows where the branch started, and it shows two occasions where changes on trunk were merged into the branch. GitHub shows none of this. In fact, the GitHub display is mostly useless in trying to figure out what happened.

Many readers have recommended various third-party GUIs for Git that might do a better job of showing historical development activity. Maybe some of them do work better than native Git and/or GitHub, though they will all be hampered by the fact that Git does not preserve historical branch names across syncs. And even if those other tools are better, the fact that it is necessary to go to a third-party tool to get the information desired does not speak well of the core system.

Git requires more administrative support

Git is complex software. One needs an installer of some kind to put Git on a developer workstation, or to upgrade to a newer version of Git. Setting up a Git server is non-trivial. One could use GitHub, but that introduces another third-party dependency and a centralized service, which mitigate the key advantage of Git which is that it is "distributed". There are various free alternatives to GitHub, such as GitLab, but those too have a lot of dependencies and require a lot of server setup.

In contrast, Fossil is a single standalone binary which is installed by putting it on $PATH. That one binary contains all the functionality of core Git and also GitHub and/or GitLab. It manages a community server with wiki, bug tracking, and forums, provides packaged downloads for consumers, login managements, and so forth, with no extra software required.

Less administration means that programmers spend more time working on the software (SQLite in this case) and less time fussing with the version control system.

Git provides a poor user experience

The following [https://xkcd.com/1597/] cartoon is an exaggeration, yet hits close to home:

Let's be real. Few people seriously dispute that Git provides a suboptimal user experience. A lot of the underlying implementation shows through into the user interface. The interface is so bad that there is even a parody site that generates [https://git-man-page-generator.lokaltog.net/|fake git man pages].

Designing software is hard. It takes a lot of focus. A good version control system should provide the developer with assistance, not frustration. Git has gotten better in this regard over the past decade, but it still has a long way to go. And so, the developers of SQLite plan to continue using a different version control system for now.

A Git-User's Guide To Accessing SQLite Source Code

If you are a devoted Git user, you can still easily access SQLite. This section gives some hints on how to do so.

GitHub Mirrors

There is a mirror of the SQLite source tree on GitHub at [https://github.com/mackyle/sqlite]. This mirror is maintained by user "mackyle" who is unaffiliated with, and unknown to, the official SQLite development team. We do not know mackyle, but we observe that he does a terrific job of keeping his mirror current, and so if you want to access the SQLite source code on GitHub, his mirror is the recommended source.

Web Access

The [https://sqlite.org/src/timeline|SQLite Fossil Repository] contains links for downloading a Tarball, ZIP Archive, or [SQLite Archive] for any historical version of SQLite. The URLs for these downloads are simple and can be incorporated easily into automated tools. The format is:

https://sqlite.org/src/tarball/VERSION/sqlite.tar.gz

Simply replace VERSION with some description of the version to be downloaded. The VERSION can be a prefix of the cryptographic hash name of a specific check-in, or the name of a branch (in which case the most recent version of the branch is fetched) or a tag for a specific check-in like "version-3.23.1":

https://sqlite.org/src/tarball/version-3.23.1/sqlite.tar.gz

To get the latest release, use "release" for VERSION, like this:

https://sqlite.org/src/tarball/release/sqlite.tar.gz

To get the latest trunk check-in, us "trunk" for VERSION:

https://sqlite.org/src/tarball/trunk/sqlite.tar.gz

And so forth. For ZIP archives and SQLite Archives, simply change the "/tarball/" element into either "/zip/" or "/sqlar/", and maybe also change the name of the download file to have a ".zip" or ".sqlar" suffix.

Fossil Access

Fossil is easy to install and use. Here are the steps for unix. (Windows is similar.)

  1. Download the self-contained Fossil executable from [https://fossil-scm.org/fossil/uv/download.html] and put the executable somewhere on your $PATH.
  2. mkdir ~/fossils
  3. fossil clone https://sqlite.org/src ~/fossils/sqlite.fossil
  4. mkdir ~/sqlite; cd ~/sqlite
  5. fossil open ~/fossils/sqlite.fossil

At this point you are ready to type "./configure; make" (or on Windows with MSVC, "nmake /f Makefile.msc").

To change your checkout to a different version of Fossil use the "update" command:

fossil update VERSION

Use "trunk" for VERSION to get the latest trunk version of SQLite. Or use a prefix of a cryptographic hash name, or the name of some branch or tag. See [https://fossil-scm.org/fossil/doc/trunk/www/checkin_names.wiki] for more suggestions on what names can be used for VERSION.

Use the "fossil ui" command from within the ~/sqlite checkout to bring up a local copy of the website.

Additional documentation on Fossil can be found at [https://fossil-scm.org/fossil/doc/trunk/www/permutedindex.html]

Do not be afraid to explore and experiment. Without a log-in you won't be able to push back any changes you make, so you cannot damage the project.

See Also

Other pages that talk about Fossil and Git include: