# CVS's problems resurface in Git

DevFeed: [CVS's problems resurface in Git](<https://devfeed.tech/articles/cvs-s-problems-resurface-in-git-21553.md>)

Original publisher: [Read original article](<http://lackingrhoticity.blogspot.com/2010/08/cvss-problems-resurface-in-git.html>)

Author: Mark Seaborn (noreply@blogger.com)

Published: 2010-08-06T20:12:00Z

Content type: opinion

Language: en

Sources: [Mark Seaborn](<https://devfeed.tech/sources/mark-seaborn.md>)

Topics: [Git](<https://devfeed.tech/topics/git.md>), [Data structures](<https://devfeed.tech/topics/data-structures.md>), [Graphs](<https://devfeed.tech/topics/graphs.md>), [systems](<https://devfeed.tech/topics/systems.md>)

Tags: [data-structure](<https://devfeed.tech/tags/data-structure.md>), [git](<https://devfeed.tech/tags/git.md>), [graph](<https://devfeed.tech/tags/graph.md>), [systems](<https://devfeed.tech/tags/systems.md>)

## AI overview

The article argues that modern version-control systems address important CVS limitations by storing history per repository as a directed acyclic graph of commit objects, but that repository-level branching, full-history checkouts, and the difficulty of combining existing repositories leave a fundamental problem unresolved.

## Source excerpt

Although modern version control systems have improved a lot on CVS, I get the feeling that there is a fundamental version control problem that the modern VCSes (Git, Mercurial, Bazaar, and I'll include Subversion too!) haven't solved. The curious thing is that CVS had sort of made some steps towards addressing it. In CVS, history is stored per file. If you commit a change that crosses multiple files, CVS updates each file's history separately. This causes a bunch of problems: CVS does not represent changesets or snapshots as first class objects. As a result, many operations involve visiting every file's history. Reconstructing a changeset involves searching all files' histories to match up the individual file changes. (This was just about possible, though I hear there are tricky corner cases. Later CVS added a commit ID field that presumably helped with this.) Creating a tag at the latest revision involves adding a tag to every file's history. Reconstructing a tag, or a time-based snapshot, involves visiting every file's history again. CVS does not represent file renamings, so the standard history tools like "cvs log" and "cvs annotate" are not able to follow a file's history from before it was renamed. In the DAG-based decentralised VCSes (Git, Mercurial, Monotone, Bazaar), history is stored per repository. The fundamental data structure for history is a Directed Acyclic Graph of commit objects. Each commit points to a snapshot of the entire file tree plus zero or more parent commits. This addresses CVS's problems: Extracting changesets is easy because they are the same thing as commit objects. Creating a tag is cheap and easy. Recording any change creates a commit object (a snapshot-with-history), so creating a tag is as simple as pointing to an already-existing commit object. However, often it is not practical to put all the code that you're interested in into a single Git repository! (I pick on Git here because, of the DAG-based systems, it is the one I am most