This page does not meet our wiki style guidelines. Please help improve this page by cleaning up its formatting. |
CVS Concepts
This page attempts to describe how the concepts familiar to CVS users correspond to the concepts employed by Mercurial, as well as highlighting functional differences between the two tools.
The structure of this topic is borrowed from the Subversion Book. Thanks, guys!
Contents
1. Some Terminology Differences
Although CVS has its own definitions for terms like "repository" (being a collection of "modules" which can be checked out, worked upon, committed to, and so on), throughout this documentation the Mercurial terminology prevails. Thus, each CVS "module" shall be known as a repository and the CVS "repository" will be referred to as a collection of repositories.
2. The Unit of Work
When committing changes in CVS, each changed file is individually committed, and it is customary to write a specific commit message which describes the work done in that file. Thus, the unit of work in CVS can be considered as the changes made to an individual file, even though a commit operation may involve a number of files at the same time.
When committing changes in Mercurial, all changes to affected files are committed together as a changeset, and it is customary to write a commit message which describes the overall effect of the work done on all affected files. Thus, the unit of work in Mercurial can be considered as the overall change to an entire repository delivered by such a changeset.
See the description of revisions for more information on how such differences in the unit of work affect revision (or version) numbering in CVS and Mercurial.
2.1. Committing
In CVS, committing causes work to be shared with the central repository, affecting other repository users when they interact with the same branch that the work was committed on. In Mercurial, a commit is a purely local operation whose effects are not shared with anyone else until a push operation is performed.
3. Workflow in Mercurial compared to CVS
The main mental difficulty when switching form CVS to Mercurial lies in the slightly different workflow (illustrated in more detail in the description of CVS-like practices for Mercurial). In Mercurial the golden rule is: if you completed a piece of work, check in, regardless of other people.
With CVS, before committing, you first need to pull in remote changes (cvs up) and merge before checking in. This of course risks that you might lose some work, it does not work as expected, and so on.
With Mercurial you first do a checkin in your local repository. Afterwards you pull in remote changes, in many cases Mercurial then creates a second head: one contains your changes, one the other people's changes. If you want to keep your head, do this:
hg merge -r other-head
Then you commit to the remote server (see Collaborating with other people below for how to get it there). The checkin-first policy allows for much more security, you can easily go back to your original version before you started with pulling in changes.
There is one point you have to pay attention when using this workflow: you need to have a tool which manages binary merge such as Joachim Eibl's KDiff3.
On Windows, newer versions of KDiff3 provide a Qt 4 version called kdiff3-QT4.exe which recognizes binary files. Pressing "cancel" and "do not save" leaves you with the version of the file you have currently in the filesystem. See TipsAndTricks and BinaryFiles for details.
4. Converting a CVS repository
For details of how to convert a CVS repository to a Mercurial repository, see ConvertingRepositories.
5. Revisions
In CVS, revision numbers describe the history of individual files: one file's revision has nothing to do with another file's revision. The notion of a collective revision number for an entire repository or group of files is traditionally provided by a tag in CVS (although recent versions of CVS provide a "commit identifier" for files committed at the same time - see the File Status section of the CVS documentation), but there are differences between CVS tags and Mercurial tags, and these are described below.
In Mercurial, revision numbers describe the history of an entire repository. Furthermore, in Mercurial, a revision number is local to a repository. To uniquely identify a changeset, use a changeset ID.
6. Disconnected operation
CVS requires that you have access to the central repository in order to perform any operation other than a simple text edit. In most collaborative situations, this repository is likely to be a remote repository (as described in the section below describing the running of a CVS server).
By contrast, a repository in Mercurial is a self-contained entity that contains the complete history of all files in the repository. You do not need to be connected to any server in order to perform any operation. You can even share your changes with others using USB memory sticks.
7. Modules, branching and tagging
CVS has a different notion of modules, branching and tagging that are often confusing to even the most experienced CVS users. As a result, relatively few CVS users appear to comfortably use features such as branching and merging in their development workflow.
7.1. Branches
When working with Mercurial, you'll find the word "branch" used for what may seem like two different concepts. The commands used for both are also different, but they both point to the same paradigm of SCM, and so are both about branching.
7.1.1. Branching by Cloning
In Mercurial, a branch is a repository. Nothing more or less. A repository is a branch. Repeat the soothing mantra.
The verb "to branch" simply means "to make a clone of a repository at a particular revision".
If every repository is a branch, how do you keep track of which one is which? That's simply a matter of convention. Mercurial has no idea which repository is the "trunk", or which is a "branch"; it's all a matter of how you use the repositories. See WorkingPractices and CvsLikePractice for some suggestions.
7.1.2. Branching inside a repository
This definition of branching is covered on the Branch page.
7.2. Tags
In CVS, a tag is a label attached to a revision on a particular file. Tagging operations tend to label many or all files in a CVS working directory with the same tag, but this need not be the case. Although such flexibility permits selective checkouts and branches, the result can often be more confusing than productive.
A Mercurial tag is just a symbolic name for a changeset. See Tag for a little more discussion.
7.3. Modules
In CVS, a module is a collection of directories that you can check out under one name.
The equivalent Mercurial concept is the repository, but there's no notion in Mercurial of "bundling" repositories together in the way that CVS bundles modules under the CVS root directory (defined by the CVSROOT environment variable). (The experimental subrepository support and the Forest extension may approximate to some of the CVS module capabilities, however.)
8. Collaborating with other people
While in CVS you get a copy of the files onto your disk, in Mercurial you get a complete repository and the files on your disk.
With CVS, the standard way to share changes with other people is simply to check them in. Some projects have a convention of posting UnifiedDiff patches to a mailing list before making a checkin.
In Mercurial, collaboration is much more flexible. You can share changes in any number of ways, including (but not limited to) the following:
Export one or more changesets and
put the exported patch files on a server for someone to download
email the patch files to a maintainer or mailing list
copy the patch files onto a memory stick and give them to someone else
Push (or rsync) the changesets into a repository from which other people can pull them
Clone a copy of the repository onto a CD-ROM and hand it to someone else
9. Running a server
With CVS, the common way to manage a server is to provide anonymous access using the pserver command, and authenticated access over ssh.
9.1. Anonymous access
In Mercurial, you can provide anonymous access using HTTP. See the Publishing Repositories document for more information.
Mercurial's own HTTP server (hg serve) provides no access controls, so anyone who can connect to your web server can clone any repositories you publish, unless you take steps to secure them in some way.
9.2. Authenticated access
Mercurial allows authenticated access to repositories, by tunnelling using the ssh command. To perform an operation over ssh, compatible versions of Mercurial must be installed on both the local and remote sides, and available through your shell's search path on the remote side.
9.2.1. Client-side password management
CVS, as part of its support for password authentication lets clients store authentication details such as passwords in a .cvspass file. To achieve similar things with Mercurial, consider using the Keyring extension or the auth section of any applicable hgrc file.
10. Watching files
CVS lets you "put a watch" on files, which requires that other developers run cvs edit before they can edit a file. Mercurial has no corresponding concept, since a Mercurial repository is a single-user entity that is not "connected" to any other.
11. Binary files
The delta algorithm used by Mercurial handles text and binary files equally well, this meaning that only the differences between revisions are stored. On the other hand, CVS was designed to work with ASCII text, and handles binary files as if they were text (i.e. treating the contents as lines separated by LF characters, and storing line-by-line deltas between revisions). For most binary files, this is very wasteful.
See workflow paragraph for remaining difficulties in using binary files with Mercurial.
12. Keywords expansion
CVS expands keywords such as $Revision: 1.12 $ by adding information from the file's CVS metadata. This feature is not in Mercurial - see Support for keyword expansion, KeywordExtension.