#pragma section-numbers 2 <> = 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 [[http://svnbook.red-bean.com/en/1.1/svn-book.html#svn-ap-a|Subversion Book]]. Thanks, guys!'' <> <> == 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|repository]] and the CVS "repository" will be referred to as a ''collection'' of [[Repository|repositories]]. <> == 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|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 [[#rev|revisions]] for more information on how such differences in the unit of work affect revision (or version) numbering in CVS and Mercurial. <> === 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 [[Cmd:Commit|commit]] is a purely local operation whose effects are not shared with anyone else until a [[Push|push]] operation is performed. <> == 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 [[CvsLikePractice|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|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 [[http://kdiff3.sourceforge.net/|KDiff3]]. {{{#!wiki tip On Windows, newer versions of KDiff3 provide a [[http://qt.nokia.com/|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. }}} <> == Converting a CVS repository == For details of how to convert a CVS repository to a Mercurial [[Repository|repository]], see ConvertingRepositories. <> == 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 [[http://ximbiot.com/cvs/manual/cvs-1.12.13/cvs_10.html#File-status|File Status]] section of the CVS documentation), but there are differences between CVS tags and Mercurial tags, and these are described below. In Mercurial, [[RevisionNumber|revision numbers]] describe the history of an entire [[Repository|repository]]. Furthermore, in Mercurial, a [[RevisionNumber|revision number]] is ''local'' to a repository. To uniquely identify a [[ChangeSet|changeset]], use a [[ChangeSetID|changeset ID]]. <> == 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 [[#server|running of a CVS server]]). By contrast, a [[Repository|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. <> == Modules, branching and tagging == CVS has a different notion of [[http://ximbiot.com/cvs/manual/cvs-1.12.13/cvs_18.html#SEC177|modules]], [[http://ximbiot.com/cvs/manual/cvs-1.12.13/cvs_5.html#SEC56|branching]] and [[http://ximbiot.com/cvs/manual/cvs-1.12.13/cvs_4.html#SEC50|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. === 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. ==== 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|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. ==== Branching inside a repository ==== This definition of branching is covered on the [[Branch]] page. === 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|tag]] is just a symbolic name for a [[ChangeSet|changeset]]. See [[Tag]] for a little more discussion. === 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|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 [[subrepos|subrepository]] support and the [[ForestExtension|Forest extension]] may approximate to some of the CVS module capabilities, however.) <> == 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: * [[Cmd:Export]] one or more [[ChangeSet|changesets]] and * put the exported [[PatchFile|patch files]] on a server for someone to download * email the [[PatchFile|patch files]] to a maintainer or mailing list * copy the [[PatchFile|patch files]] onto a memory stick and give them to someone else * [[Cmd:Push]] (or rsync) the [[ChangeSet|changesets]] into a [[Repository|repository]] from which other people can [[Cmd:Pull|pull]] them * [[Cmd:Clone]] a copy of the [[Repository|repository]] onto a CD-ROM and hand it to someone else <> == 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}}}. === Anonymous access === In Mercurial, you can provide anonymous access using HTTP. See the [[PublishingRepositories|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. === 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. ==== Client-side password management ==== CVS, as part of [[http://ximbiot.com/cvs/manual/cvs-1.12.13/cvs_2.html#SEC32|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 [[KeyringExtension|Keyring extension]] or the [[http://www.selenic.com/mercurial/hgrc.5.html#auth|auth section]] of any applicable `hgrc` file. <> == 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|repository]] is a single-user entity that is not "connected" to any other. <> == 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|workflow]] paragraph for remaining difficulties in using [[BinaryFiles|binary files]] with Mercurial. <> == 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 [[http://www.selenic.com/pipermail/mercurial/2005-August/003887.html|Support for keyword expansion]], [[KeywordExtension]].