The History of Version Control
Version control is the systematic management of changes to documents, computer programs, large web sites, and other collections of information. In software engineering, version control systems track the history of source code, allowing developers to revert to previous states, branch development into parallel tracks, and merge independent modifications.[31] The discipline emerged from the physical constraints of mainframe computing, where managing decks of punched cards required strict physical procedures to prevent data loss. As software complexity grew, the need for automated and auditable change management drove the evolution of dedicated version control software.
The technical progression of version control divides into three distinct generations. The first generation relied on local file systems and pessimistic locking, ensuring that only one developer could edit a file at a time. The second generation introduced centralized servers and optimistic concurrency, allowing multiple developers to edit files simultaneously and merge their changes later over a local area network. The third generation decentralized the repository entirely, utilizing cryptographic hashes and directed acyclic graphs to treat every developer's local copy as a complete and independent repository.
Today, version control is the foundational infrastructure of collaborative software development.[32] It enables continuous integration, automated testing, and distributed asynchronous collaboration across global teams. The shift from local scripts to centralized servers, and finally to distributed cryptographic graphs, reflects broader trends in computer science regarding network latency, storage costs, and the mathematical modeling of concurrent systems.
The Prehistoric Era: Punched Cards and Magnetic Tape (1960s to 1970s)
Before dedicated version control software existed, programmers managed source code physically. In the 1960s, programs for mainframes like the IBM System/360[1] were stored on punched cards[2]. A single program could require thousands of cards. The standard IBM punched card featured 80 columns. Programmers used columns 1 through 72 for the actual code statements, while columns 73 through 80 were strictly reserved for sequence numbers. These sequence numbers were critical for physical data integrity. If a programmer accidentally dropped a deck of cards, they could feed the scattered cards into a mechanical card sorting machine, which would read the sequence numbers and automatically place the deck back into the correct order.
To make a change to a program, a developer physically removed a card from the deck, typed a new card using a machine like the IBM 029 keypunch, and inserted the new card in the correct sequence. Backups consisted of duplicating the entire deck using specialized card reproducing machines or copying the deck contents to magnetic tape.
To automate this physical process, computer manufacturers provided librarian programs. IBM introduced IEBUPDTE[3] for the OS/360 operating system, a utility that applied sequential updates to sequential data sets. Control Data Corporation provided a similar utility named UPDATE for its CDC 6000 series mainframes. These tools relied heavily on the sequence numbers to identify which lines to replace, delete, or insert.
In 1969, Applied Data Research released a commercial software product named The Librarian[4]. The Librarian was designed to supplant physical punched card decks by storing the version controlled program in master files on magnetic tape. The software became one of the best selling products in the computer industry during the 1970s. The value of these master files was demonstrated dramatically in November 1969 when a light aircraft crashed into the Applied Data Research headquarters in Princeton, New Jersey. The building caught fire, but staff members successfully rescued the magnetic tapes containing The Librarian master files from the blaze, preserving the company source code (Retrocomputing Stack Exchange[5]).
In practice, early systems stored a base version of the program on magnetic tape. When a programmer needed to modify the code, they submitted a deck of modification cards, known as a patch deck, along with the compilation job. A patch deck contained specific commands, such as an instruction to delete lines 500 through 550, followed by the new punched cards to insert. The librarian program read the base tape, copied the unmodified lines to a new tape, applied the patch deck in memory based on the sequence numbers, and fed the resulting source code to the compiler. This approach saved expensive disk space but required linear processing of the entire file to apply changes. It also offered no mechanism to track who made a change, when the change occurred, or why the modification was necessary.
The First Generation: Local File Locking (1972 to 1985)
The transition from batch processing to interactive time sharing systems, such as Unix and OS/MVT, moved source code from physical cards to magnetic disk drives. This shift necessitated new software tools for managing file revisions directly on the disk.
The Source Code Control System (SCCS)
In 1972, Marc Rochkind at Bell Labs developed the Source Code Control System (SCCS)[6] for an IBM System/370 computer running OS/MVT, later porting the software to Unix. Rochkind published the formal design in the IEEE Transactions on Software Engineering[7] in December 1975. SCCS introduced the concept of the delta, storing only the differences between versions rather than saving full copies of the file every time a change was made.
SCCS used an interleaved delta format. It wove all versions of a file into a single master file, using control characters to indicate which lines belonged to which version. The control records started with the ASCII Start of Heading character (octal 001) to mark the beginning and end of changes. When a user requested a specific version, SCCS read the master file sequentially from top to bottom, evaluating the boolean logic of the control records against the requested version number, and output the valid lines. Because of this interleaved structure, retrieving version 1 took the exact same amount of processing time as retrieving version 50.
SCCS implemented pessimistic concurrency control. To edit a file, a developer executed a get command with an edit flag, which placed a strict lock on the file. No other developer could edit the file until the first developer checked it back into the system. This locking mechanism prevented merge conflicts but created severe bottlenecks when multiple developers needed to modify different functions within the same file simultaneously.
The Revision Control System (RCS)
In 1982, Walter Tichy at Purdue University developed the Revision Control System (RCS)[8], publishing its design in the journal Software: Practice and Experience[9] in July 1985. RCS addressed the performance limitations of the interleaved delta format used by SCCS. Tichy observed that as an SCCS file accumulated more revisions, the file grew larger and the boolean logic became more complex, slowing down every operation. Tichy also noted that developers most frequently access the newest version of a file.
Consequently, RCS stored the most recent version intact as plain text and stored historical versions as reverse deltas. To retrieve an older version, RCS started with the current text and applied the edit scripts backward. This architecture minimized processing overhead for the most common operations. RCS files were easily identifiable on Unix systems by their ,v file extension.
RCS maintained the pessimistic locking model of SCCS. It operated strictly on single files, lacking the concept of a multi file project or an atomic commit. If a feature required changes to five different files, the developer locked and committed each file individually. Despite these architectural limitations, RCS became the standard version control tool for Unix systems throughout the 1980s and 1990s, and its reverse delta concept heavily influenced later systems.
The Second Generation: Centralized Networking (1986 to 2000)
As local area networks proliferated, software development shifted from single time sharing mainframes to networks of individual workstations. This hardware evolution required version control systems that could operate over a network and handle concurrent development from multiple client machines.
The Concurrent Versions System (CVS)
In 1986, Dick Grune created a series of shell scripts to wrap RCS, allowing developers to work on collections of files simultaneously. He named the project the Concurrent Versions System (CVS)[10]. In 1989, Brian Berliner translated these scripts into the C programming language, adding native network support for his employer Prisma. Berliner published the architecture in the paper "CVS II: Parallelizing Software Development"[11] at the 1990 USENIX Winter Conference.
CVS introduced optimistic concurrency control, also known as the copy modify merge model. Instead of locking files, developers checked out a working copy of the repository to their local machine, made changes freely, and then committed those changes to the central server. If another developer had modified the same file in the interim, the server rejected the second commit. The second developer was required to pull the latest changes, merge them locally, resolve any textual conflicts, and then attempt the commit again. This model eliminated the bottlenecks of pessimistic locking and became the standard workflow for open source development.
CVS operated over a client server architecture, utilizing a daemon called pserver or operating securely over SSH. To track metadata, CVS created a hidden CVS subdirectory inside every folder of the working copy, which recorded the repository URL and the base revision of each file.
However, CVS had severe architectural flaws. It tracked history per file rather than per repository, meaning a commit spanning multiple files was not atomic. If a network failure occurred halfway through a commit, the repository was left in a corrupted and inconsistent state. CVS also struggled with renaming or moving files, as its underlying RCS files were permanently tied to specific file paths.
Commercial Alternatives: ClearCase, Perforce, and Visual SourceSafe
The limitations of CVS created a lucrative market for commercial enterprise systems. In 1992, Atria Software released ClearCase[12]. ClearCase used a proprietary MultiVersion File System (MVFS) that integrated directly into the operating system kernel. This allowed developers to mount a specific version of a repository, called a Versioned Object Base (VOB), as a virtual disk drive. The Internet Assigned Numbers Authority officially allocated TCP and UDP ports 371 to ClearCase in RFC 1340[13]. ClearCase supported both dynamic views, which updated instantly over the network, and snapshot views, which copied files locally.
In 1995, Christopher Seiwald founded Perforce[14], offering a centralized system optimized for high performance and large binary assets. Perforce became highly popular in the video game industry, where repositories often contained gigabytes of graphical and audio assets that text oriented systems like CVS could not handle efficiently.[33]
Conversely, Microsoft acquired One Tree Software in 1994 and rebranded its product as Visual SourceSafe (VSS)[15]. Visual SourceSafe relied heavily on pessimistic file locking and stored data in a shared file system database rather than a true client server relational database. Clients read and wrote directly to the database files over the Server Message Block (SMB) protocol. If a network connection dropped during a write operation, the database files were frequently corrupted. This architecture made Visual SourceSafe notorious for data loss and extremely slow history generation, serving as a cautionary example of poor version control design throughout the late 1990s. Microsoft eventually replaced it with Team Foundation Server.
Apache Subversion (SVN)
By the late 1990s, the open source community urgently needed a replacement for CVS. In 2000, CollabNet initiated the Subversion (SVN)[16] project, led by developers Karl Fogel and Jim Blandy, with the explicit goal of being CVS done right. Subversion fixed the most glaring flaws of its predecessor. It introduced atomic commits using a database transaction model, ensuring that a multi file change either succeeded completely or failed completely. It versioned directories as first class objects, allowing files to be renamed and moved without losing their historical context.[34]
Subversion used a strict centralized client server architecture. Initially, it stored repository data using the Berkeley DB database system, but later switched to a custom plain file format called FSFS to improve reliability and prevent database corruption over network shares. Subversion handled branching by copying a directory path to a new path using the svn copy command. This operation was highly efficient in time and space because it only created a database link, known as a cheap copy. However, Subversion struggled with tracking merges between these copies, requiring developers to manually record which revisions had been merged.[35] Despite this limitation, Subversion became the dominant version control system of the 2000s, adopted by the Apache Software Foundation and thousands of corporate engineering teams.
The Third Generation: Distributed Version Control (2000 to 2005)
Centralized systems like Subversion required a constant network connection to view history, create branches, or commit changes. The Linux kernel project, with thousands of contributors spread globally across different time zones, found centralized systems entirely inadequate for their workflow.
BitKeeper and the Linux Kernel
In 1998, Larry McVoy, a former Sun Microsystems engineer who had worked on the internal Sun TeamWare system, founded BitMover, but BitKeeper was first publicly released in 2000[17]. BitKeeper was a distributed version control system (DVCS). In a DVCS, there is no single central server required for daily operations. Every developer clones the entire repository, including its full history, to their local machine.[36] Commits are made locally, and developers synchronize their repositories by pushing and pulling changes directly between peers or through a shared host.
In 2002, Linus Torvalds, the creator of Linux, chose BitKeeper to manage the Linux kernel source code. BitKeeper was proprietary software, but McVoy granted a free license to open source projects, provided the developers did not attempt to reverse engineer the software or develop competing tools. This decision was highly controversial within the free software community, drawing intense criticism from Richard Stallman and the Free Software Foundation.
The 2005 BitKeeper Controversy
The uneasy alliance between the Linux community and BitMover collapsed in April 2005. Andrew Tridgell, the creator of the Samba file server, wrote an open source tool called SourcePuller[18] that could extract data from a BitKeeper repository. Tridgell stated he did not decompile the BitKeeper binary but instead analyzed the network packets and text outputs to understand the protocol. McVoy argued this violated the license agreement and promptly revoked the free use of BitKeeper for Linux developers.
The Creation of Git
Faced with the sudden loss of BitKeeper, Torvalds evaluated existing open source alternatives but found them too slow for the massive Linux kernel codebase. On April 3, 2005, Torvalds began writing his own system. He named it Git[19].
Torvalds designed Git not as a traditional version control system, but as a content addressable filesystem. Instead of storing file differences, Git stores snapshots of the entire directory tree. The architecture relies on four primary object types: blobs for file contents, trees for directory listings, commits for metadata and pointers to trees, and tags. Every object is hashed using the SHA-1[20] cryptographic algorithm, producing a 40 character hexadecimal string. This hash serves as the permanent identifier of the object. If a single byte in a file changes, its hash changes, which changes the hash of its parent directory, cascading all the way up to the commit object. This design guarantees cryptographic integrity. It is mathematically impossible to alter history without changing the commit hashes, effectively making the repository a Merkle tree[21].
Git models repository history as a directed acyclic graph (DAG). A commit contains a pointer to its tree object, the author name, a timestamp, and a list of parent commit hashes. An initial commit has zero parents, a normal commit has one parent, and a merge commit has two or more parents. A branch in Git is not a physical copy of files, but simply a 41 byte file containing a lightweight movable pointer to a specific commit hash. This made branching and merging nearly instantaneous local operations. Torvalds released the first version of Git to the Linux Kernel Mailing List[22] on April 7, 2005.
Mercurial, Monotone, and Bazaar
Git was not the only DVCS created in 2005. On April 19, 2005, Matt Mackall released Mercurial[23], another distributed system designed as a replacement for BitKeeper. Mercurial was written primarily in Python and prioritized a clean and intuitive command line interface, contrasting with the initially steep learning curve of Git. While Git compressed older objects into packfiles, Mercurial used an append only data structure called a revlog to store file revisions efficiently.
Both Git and Mercurial drew theoretical inspiration from Monotone[24], a DVCS started by Graydon Hoare in 2003. Monotone pioneered the use of cryptographic hashes to identify file revisions and the use of a DAG to represent history. It relied heavily on SQLite for storage and RSA certificates for authentication. However, Monotone suffered from performance issues that prevented its adoption for the Linux kernel, leaving the market open for Git and Mercurial. Another competitor, Bazaar, developed by Canonical, focused heavily on user experience but ultimately lost the market share war to Git due to performance limitations.
The Modern Era: Hosting Platforms and Code Review (2008 to Present)
The distributed nature of Git and Mercurial solved the problem of local branching and merging, but it created a new challenge regarding code discovery. Because every clone is a full repository, developers needed a standardized way to publish their repositories and propose changes to project maintainers.
The Rise of GitHub and GitLab
GitHub was founded by Chris Wanstrath, PJ Hyett, Tom Preston-Werner, and Scott Chacon, and publicly launched in April 2008 (though a private beta began in February)[25], a web based hosting service for Git repositories. GitHub introduced the pull request, a web interface that allowed a developer to fork a repository, push changes to their fork, and notify the project maintainer that they wanted those changes merged into the main repository. The pull request transformed code review from an email based patch process into a visual and asynchronous discussion attached directly to the source code.
In 2011, Dmitriy Zaporozhets and Valery Sizov created GitLab[26], an open source alternative to GitHub. GitLab expanded the scope of version control hosting by integrating Continuous Integration and Continuous Deployment (CI/CD) pipelines directly into the repository platform. When a developer pushes a commit, the platform automatically provisions virtual machines to compile the code, run unit tests, and deploy the application to production servers.
Enterprise Scale and Virtual File Systems
By the late 2010s, Git achieved near total dominance in the software industry. Microsoft, which had historically maintained its own centralized systems, adopted Git for Windows development and acquired GitHub in 2018.
The scale of modern enterprise repositories pushed the limits of the original Git design. Monorepos, where a company stores all its source code in a single repository, require specialized tools to handle the sheer volume of data. Google operates the largest known monorepo in the world, managed by a custom version control system named Piper. As detailed in a 2016 Communications of the ACM[27] paper by Rachel Potvin and Josh Levenberg, the Google repository contained over two billion lines of code and spanned 86 terabytes of data. Piper utilizes trunk based development, where thousands of engineers commit directly to a single main branch. To maintain codebase health at this scale, Google built integrated tools like Critique for code review, Tricorder for static analysis, and Rosie for large scale refactoring.
Similarly, the Microsoft Windows repository contains approximately 3.5 million files and consumes over 300 gigabytes of storage. Cloning this repository using standard Git would take hours and exhaust the memory of a standard developer workstation. To solve this, Microsoft developed the Virtual File System for Git (VFS for Git)[28], later evolving into the Scalar project. These tools intercept operating system file calls, dynamically downloading only the specific files a developer accesses. This approach blends the distributed graph model of Git with the partial checkout capabilities of older centralized systems like ClearCase and Perforce.
Modern State and Significance
The architecture of modern version control has fundamentally altered software engineering. The ability to create cheap and disposable branches enables feature branch workflows, where every new feature or bug fix is developed in strict isolation before being merged. Cryptographic hashing ensures supply chain security, allowing automated systems to verify that the code compiled is exactly the code reviewed and approved by human developers.
Version control has also expanded far beyond traditional software engineering. Data scientists use tools like Data Version Control (DVC)[29] to track machine learning models and massive datasets. DVC applies Git semantics to large binary files, storing the actual data in cloud object storage while keeping lightweight metadata pointers in the Git repository. This ensures that machine learning experiments remain reproducible and auditable.
In addition, the practice of Infrastructure as Code relies on Git repositories to define cloud server configurations. Under the methodology known as GitOps[30], the Git repository serves as the single source of truth for infrastructure deployment. Automated agents continuously monitor the repository and pull changes into platforms like Kubernetes, ensuring that physical hardware deployments are as auditable and reversible as software changes. The mathematical model of the directed acyclic graph, combined with cryptographic integrity, has proven to be a universal solution for managing the evolution of complex digital information.
Sources (36)
- Wikipedia: IBM System/360
- Wikipedia: punched cards
- IBM
- Wikipedia: The Librarian
- Retrocomputing Stack Exchange
- Wikipedia: Source Code Control System (SCCS)
- IEEE
- Wikipedia: Revision Control System (RCS)
- Software: Practice and Experience
- Wikipedia: Concurrent Versions System (CVS)
- "CVS II: Parallelizing Software Development"
- IBM
- IETF
- Perforce
- Wikipedia: Visual SourceSafe (VSS)
- Subversion (SVN)
- Wikipedia: BitKeeper
- Wikipedia: SourcePuller
- git-scm.com
- SHA-1
- Wikipedia: Merkle tree
- Linux Kernel Mailing List
- Mercurial
- Monotone
- GitHub
- GitLab
- ACM Digital Library
- Virtual File System for Git (VFS for Git)
- Data Version Control (DVC)
- GitOps
- David Nicolette, Software Development Metrics (Simon and Schuster, 2015)
- Mathias Olausson, Jakob Ehn, Continuous Delivery with Visual Studio ALM 2015 (Apress, 2015)
- Pete Goodliffe, Code Craft (No Starch Press, 2007)
- Stephen Chin, Melissa McKay, Ixchel Ruiz, DevOps Tools for Java Developers ("O'Reilly Media, Inc.", 2022)
- Peter R. King, Proceedings of the 2005 ACM Symposium on Document Engineering (Association for Computing Machinery (ACM), 2005)
- Nico Loubser, The Developer's Field Guide to Modern Software Engineering (Springer Nature, 2026)