Git: A Journey Through Version Control History
Twenty years ago, a disagreement over licensing terms sparked the creation of what would become the world’s most popular version control system.
In April 2005, the Linux kernel development community faced a crisis. They had been using BitKeeper, a proprietary version control system, under a free-of-charge license. When that arrangement collapsed due to licensing disagreements, Linus Torvalds—the creator of Linux—decided to build his own version control system rather than adopt any of the existing alternatives.
In just a few days of intense coding, Git was born. On April 7, 2005, Linus made the initial commit to the Git repository. True to his practical nature, Git was self-hosting almost immediately—meaning Git was used to version-control itself from nearly the beginning.
e83c516: The information manager from hell
The Original Commands
I thought it might be fascinating to compare and contrast how similar or different Git was compared to what we know today. The initial commit included these core binaries:
Original Command (2005) | Modern Equivalent | What It Does |
---|---|---|
init-db | git init | Creates a new repository |
update-cache | git add | Stages files to the index |
write-tree | Part of git commit | Converts staged changes into a tree object |
commit-tree | Part of git commit | Creates a commit from a tree |
read-tree | Internal operation | Reads tree data into the index |
show-diff | git diff | Shows changes between working directory and index |
read-cache | git ls-files | Shows what’s in the index |
Each command was a separate executable—no unified interface or integrated help system.
These commands exposed Git’s internal object model directly to users. There was no unified git
command with subcommands yet—just separate executables that each performed a specific low-level function.
Creating a Commit in 2005 vs. Today
Let’s look at what it took to make a simple commit in the original version:
The 2005 Experience:
./init-db # Initialize repository
echo "Hello, Git history" > hello.txt # Create a file
./update-cache --add hello.txt # Stage the file
TREE=$(./write-tree) # Create a tree object
COMMIT=$(echo "Initial commit" | ./commit-tree $TREE) # Create a commit
echo "Created commit: $COMMIT" # Display the commit hash
Today’s Equivalent:
git init
echo "Hello, Git history" > hello.txt
git add hello.txt
git commit -m "Initial commit"
The original process exposed Git’s internal plumbing—manually managing trees and commit objects. Modern Git handles this complexity, and tools like LazyGit (which I love) further simplify the workflow through intuitive interfaces.
Git’s Core Design
Despite its rough edges, Linus’s original creation already embodied the design principles that would make Git successful:
- Distributed development - No central server required
- Data integrity - Content-addressed storage with SHA-1 hashing
- Performance - Speed was a primary concern from day one
- Branching and merging - First-class support for non-linear development
These principles remain at the heart of Git today, even as its user interface has been dramatically refined.
Git’s Evolution
Over the past two decades, Git has evolved from these humble beginnings to become the dominant version control system worldwide:
- The unified
git
command structure was introduced, creating a more cohesive user experience - Documentation and tutorials proliferated
- Platforms like GitHub (2008) and GitLab (2011) built experiences on top of Git
- Enterprise adoption accelerated
- Performance improvements for massive repositories
- New features like Git-LFS addressed limitations of large binaries
- Enhanced user interfaces—from terminal-based tools like LazyGit and tig to graphical clients like GitHub Desktop and GitKraken
Yet, the mental model—a content-addressable filesystem with a staging area (index) and commit objects that point to trees—remains fundamentally unchanged.
The Lessons of Git
Git’s evolution teaches the valuable lesson:
- Solve your own problems - Linus built Git because he needed it for Linux development
- Focus on fundamentals - Getting the data model right enabled everything else
- Embrace iteration - Git’s user experience improved dramatically over time
- Community matters - Git thrived because of contributions from a growing community
- Good plumbing enables good interfaces - The solid foundation allowed for better interfaces to be built later
I’ve come to really appreciate just how far we’ve come from those early days of update-cache
and commit-tree
.