The Story Behind Git

Born from a licensing dispute and built in fury, Git became the version control system that powers nearly all modern software development.

The Breakup

In April 2005, the Linux kernel community faced a crisis. For three years, they had used BitKeeper, a proprietary distributed version control system whose creator, Larry McVoy, offered free licenses to open source developers. The arrangement was contentious from the start. Stallman and others objected to a free software project depending on proprietary tools. Then Andrew Tridgell, an Australian developer famous for reverse-engineering SMB to create Samba, began probing BitKeeper's protocol. McVoy considered this a violation of the free license terms and revoked access for all Linux developers.

Linus Torvalds was furious. Not at Tridgell, not at McVoy, but at the situation. The Linux kernel, one of the most important software projects in history, had no version control system. Existing open source alternatives (CVS, Subversion) were centralized, slow, and architecturally incapable of handling the kernel's development workflow. Torvalds decided to build something new.

Built in Two Weeks

Torvalds started writing Git on April 3, 2005. By April 7, it was self-hosting (managing its own source code). By April 18, the first merge of multiple branches was completed. By June 16, Linux kernel 2.6.12 was released using Git. The speed was extraordinary, even by Torvalds's standards.

The name "Git" is British slang for an unpleasant person. Torvalds said, "I'm an egotistical bastard, and I name all my projects after myself. First Linux, now git." The README file originally described it as "the stupid content tracker." Both characterizations contain more honesty than humor.

Git's design reflected Torvalds's priorities, shaped by years of managing the kernel. It had to be fast (processing patches from hundreds of developers), distributed (no single point of failure), and resistant to corruption (bit-rot in a repository would be catastrophic). He also explicitly designed it as the opposite of CVS: "Take CVS as an example of what not to do; if in doubt, make the exact opposite decision."

The Content-Addressable Filesystem

At its core, Git is not really a version control system. It is a content-addressable filesystem with a version control interface layered on top. Every object in Git (files, directories, commits) is stored by the SHA-1 hash of its contents. This means identical content is automatically deduplicated, and any corruption is immediately detectable.

A commit in Git is just a text file containing a pointer to a tree (which represents the directory structure), pointers to parent commits, and metadata (author, timestamp, message). A branch is just a file containing a 40-character hash pointing to a commit. This simplicity is Git's genius. Complex operations like branching and merging, which were expensive in older systems, become trivial pointer manipulations.

The Steep Learning Curve

Git's interface was, and remains, notoriously confusing. The same command (git checkout) historically did completely different things depending on context: switching branches, restoring files, creating branches. The distinction between the working directory, staging area (index), and repository confuses beginners. The reflog, detached HEAD state, and interactive rebase are powerful but intimidating.

Part of the confusion stems from Git's origins as a toolkit rather than a product. Torvalds built the low-level "plumbing" commands and expected others to build friendly "porcelain" on top. The porcelain that exists was added incrementally by many contributors with different design sensibilities. Recent versions have improved the situation (git switch and git restore replaced some uses of git checkout), but Git's reputation as difficult persists.

GitHub, GitLab, and the Social Layer

Git is distributed by design. Every clone contains the full history. You do not need a central server. In practice, nearly everyone uses a central hosting service, and GitHub became the dominant one after launching in 2008. GitHub added a social layer, pull requests, issues, wikis, and profiles, that transformed Git from a tool into a platform.

GitLab (founded 2011) offered a self-hosted alternative with integrated CI/CD. Bitbucket (acquired by Atlassian in 2010) integrated with the Jira ecosystem. But GitHub's network effects were overwhelming. By the time Microsoft acquired it in 2018, GitHub hosted over 100 million repositories.

The Data Model in Detail

Understanding Git requires understanding its four object types. A blob stores the contents of a single file. A tree stores a directory listing, mapping filenames to blob hashes (for files) or other tree hashes (for subdirectories). A commit stores a pointer to a tree (the project snapshot), pointers to parent commits, author information, and a message. A tag stores a pointer to a commit along with a name and optional signature.

This model has elegant implications. If you change one file in a project with 10,000 files, Git creates one new blob (for the changed file), new tree objects for every directory in the path from root to the changed file, and one new commit. The other 9,999 files are not copied. They are referenced by their existing hashes. This is why Git repositories are compact despite storing complete history: identical content is stored exactly once.

Branches in Git are simply pointers to commits. Creating a branch costs nothing: Git writes a 41-byte file (a 40-character SHA-1 hash plus a newline) to .git/refs/heads/. Switching branches updates the HEAD pointer and checks out the corresponding tree. This cheapness is why Git encourages a branching workflow that would be impractical in systems where branches are expensive copies (like early Subversion).

Merging exploits the data model's structure. Git finds the common ancestor of two branches (the "merge base"), computes the differences each branch introduced since the ancestor, and combines them. If both branches modified the same lines, Git reports a conflict. Otherwise, the merge is automatic. The three-way merge algorithm, combined with cheap branches, is what makes Git's workflow possible.

The Staging Area: Git's Controversial Feature

The staging area (also called the "index") is one of Git's most distinctive and most debated features. Before committing, you explicitly add changes to the staging area with git add. This creates an intermediate step between "modified" and "committed" that other version control systems lack.

The staging area enables partial commits: you can modify five files but commit changes from only two of them. You can even stage individual lines within a file using git add -p (patch mode). This granularity lets developers craft clean, logical commits from messy work-in-progress changes.

Critics argue the staging area adds unnecessary complexity. Mercurial, Git's closest competitor, does not have one, and Mercurial users do not generally miss it. The counterargument is that the staging area encourages a discipline of small, focused commits that makes history more useful. A commit that says "fix login bug" is more useful than one that says "fix login bug, also refactor database layer, also update dependencies."

How Git Handles Large-Scale Development

The Linux kernel, Git's original use case, is one of the largest collaborative software projects in history. Over 15,000 developers have contributed to the kernel, with thousands active in any given release cycle. Git's design decisions make sense in this context.

The distributed model means that subsystem maintainers can manage their own repositories, reviewing and integrating patches from contributors before passing them upstream to Linus Torvalds. This "lieutenant" model scales because no single repository or server is a bottleneck. Each maintainer has the complete history and can work offline.

Git's performance at scale required continuous optimization. The packfile format compresses objects by storing deltas (differences) between similar objects. The bitmap index accelerates clone and fetch operations by precomputing reachability information. The commit graph file speeds up history traversal. These optimizations are invisible to users but essential for repositories with millions of objects and decades of history.

Microsoft's migration of the Windows codebase to Git (announced in 2017) pushed Git's limits. The Windows repository contained over 300 GB of source code with 3.5 million files. Microsoft developed GVFS (Git Virtual File System, later renamed VFS for Git) to handle this scale, virtualizing the filesystem so that files were downloaded on demand rather than all at once. This work contributed to Git's "partial clone" and "sparse checkout" features, which benefit any large repository.

The Ecosystem Beyond GitHub

While GitHub dominates mindshare, the Git ecosystem is broader than a single platform. GitLab, initially a self-hosted GitHub alternative, evolved into a comprehensive DevOps platform with built-in CI/CD, container registry, package registry, and security scanning. Many enterprises, particularly in regulated industries, prefer GitLab's self-hosted model for data sovereignty.

Gitea and Forgejo provide lightweight, self-hosted Git platforms for teams that want simplicity over features. Gerrit, developed by Google, provides a code review workflow used by Android, Chromium, and other large projects. Each platform adds its own conventions on top of Git's primitives.

The pull request (or merge request, in GitLab's terminology) is the most important workflow convention built on Git. It was not part of Git itself but was invented by GitHub as a mechanism for proposing, discussing, and reviewing changes. The pull request transformed open source contribution from "email a patch to a mailing list" to "click a button and fill out a form." This lowered the barrier to contribution so dramatically that it changed the demographics of open source.

The Data Model in Detail

Understanding Git requires understanding its four object types. A blob stores the contents of a single file, identified by the SHA-1 hash of that content. A tree stores a directory listing, mapping filenames to blob hashes (for files) or other tree hashes (for subdirectories). A commit stores a pointer to a tree (the project snapshot), pointers to parent commits, author information, and a message. A tag stores a pointer to a commit along with a name and optional cryptographic signature.

This model has elegant implications. If you change one file in a project with 10,000 files, Git creates one new blob (for the changed file), new tree objects for every directory in the path from root to the changed file, and one new commit. The other 9,999 files are not copied. They are referenced by their existing SHA-1 hashes. This is why Git repositories are compact despite storing complete history: identical content is stored exactly once, regardless of how many commits reference it.

Branches in Git are simply pointers to commits. Creating a branch costs almost nothing: Git writes a 41-byte file containing a SHA-1 hash to the refs directory. Switching branches updates the HEAD pointer and checks out the corresponding tree. This cheapness is why Git encourages a branching workflow that would be impractical in systems where branches are expensive copies.

Merging exploits the data model structure. Git finds the common ancestor of two branches (the merge base), computes the differences each branch introduced since the ancestor, and combines them. If both branches modified the same lines, Git reports a conflict. Otherwise, the merge is automatic. The three-way merge algorithm, combined with cheap branches, is what makes Git collaborative workflow possible.

The Staging Area

The staging area (also called the index) is one of Git's most distinctive and most debated features. Before committing, you explicitly add changes to the staging area with git add. This creates an intermediate step between "modified" and "committed" that most other version control systems lack.

The staging area enables partial commits: you can modify five files but commit changes from only two of them. You can even stage individual hunks within a file using patch mode. This granularity lets developers craft clean, logical commits from messy work-in-progress changes. A commit that says "fix login timeout bug" is more useful in the history than one that says "fix login bug, also refactor database layer, also update dependencies."

Critics argue the staging area adds unnecessary complexity. Mercurial, Git's closest competitor, does not have one, and Mercurial users do not generally miss it. The counterargument is that the staging area encourages a discipline of small, focused commits that makes history more useful for debugging, code review, and understanding the evolution of a codebase.

Git at Scale

The Linux kernel, Git's original use case, is one of the largest collaborative software projects in history. Over 15,000 developers have contributed, with thousands active in any given release cycle. Git's design decisions make sense in this context.

The distributed model means that subsystem maintainers can manage their own repositories, reviewing and integrating patches from contributors before passing them upstream to Torvalds. This lieutenant model scales because no single repository or server is a bottleneck. Each maintainer has the complete history and can work offline.

Git's performance at scale required continuous optimization. The packfile format compresses objects by storing deltas between similar objects rather than full copies. The bitmap index accelerates clone and fetch operations by precomputing reachability information. The commit graph file speeds up history traversal for repositories with millions of commits. These optimizations are invisible to users but essential for large repositories.

Microsoft's migration of the Windows codebase to Git pushed the system's limits. The Windows repository contained over 300 GB of source code with 3.5 million files. Microsoft developed VFS for Git to handle this scale, virtualizing the filesystem so that files were downloaded on demand rather than all at once.

Git Workflows

Different teams have adopted different branching strategies built on Git's primitives:

Git Flow (Vincent Driessen, 2010): A structured model with develop and main branches, feature branches, release branches, and hotfix branches. Popular in the early 2010s but now considered overly complex for most teams.

GitHub Flow: A simplified model where all work happens on feature branches created from main. Pull requests are used for code review, and branches are merged to main when approved. Continuous deployment means main is always in a deployable state.

Trunk-Based Development: Developers commit directly to main (or to very short-lived feature branches merged within hours). This requires strong CI/CD practices and feature flags. Google, Facebook, and other large companies practice trunk-based development.

The choice of workflow depends on team size, release cadence, and risk tolerance. The flexibility to support all of these models from the same underlying tool is part of what made Git successful.

Key Takeaways

The Legacy

Git did not just replace older version control systems. It changed how developers think about collaboration. Feature branches, pull requests, and code review workflows are now standard practices that barely existed before Git. The fork-and-pull-request model democratized open source contribution. The idea that every developer has a complete copy of the repository, including full history, changed the relationship between developers and their code.

Torvalds has said that Git is his most important contribution to software, more important than Linux. It is a bold claim, but a defensible one. Linux runs much of the world's infrastructure. Git changed how all software, not just Linux, is built.