Version Control Basics
This is a basic introduction to Version Control Systems (VCS) such as CVS (Concurrent Versioning System) and SVN (subversion).
There are six well-known suites of version control software (VCS). All are unix tools geared towards version of text files (such as source code or configuration files).
RCS, CVS, subversion and git clearly represent an evolution of version control software.
- RCS (Revision Control System)
- RCS is the original version control software which can only be used on a local host. It is still used for version control of configuration files.
- CVS (Concurrent Versions System)
- CVS adds a client/server model, which makes it very useful for version control of source code. It is no longer in common use.
- Subversion (SVN)
- Subversion further increased by adding support for file or folder renaming (which CVS lacks). Furthermore, subversion is slightly simpler to use by dropping support for tags and trunks (by convention folders are used for tags and trunks).
- RCS, SVN and subversion only support a linear history: later version always obsolete earlier versions. GIT instead support code branching, making each check-out a repository a stand-alone one. This makes git more useful for large projects with many branches. Since git really replicates the full repository (including all changes) it is possible to view the whole history, even when you are off-line.
- Mercurial (Hg)
- Mercurial is a distributed system (like git), but stores full version (like subversion) instead of changes. This makes it more suitable for large files or binary files then git.
- A smaller project, similar to Mercurial.
I'm currently mostly using git, and sometimes mercurial.
Usually, git is a good choice. Mercurial is a good choice for novices (as it is harder to break things in Mercurial, and easier in Git). Subversion is still a decent choice if you the versioning is and always will be lineair, without branches.
CVS, SVN and GIT perform actions based on the subcommand you give it. While the terminology between CVS and SVN is very similar, it is slightly different for GIT.
|Download changes||update||update||pull (= fetch + merge)||pull|
|Register new files||add||add||add||add|
|Register removed files||remove||remove||rm||remove|
|Register renamed files||- (unsupported)||move||mv||move|
|Register changed files||- (automatic)||- (automatic)||add||add|
|Store changes locally||- (automatic)||- (automatic)||commit||commit|
|List current changes||status||status||status||status|
|Project info||- (cat CVS/Root)||info||- (cat .git/config)||- (cat .hg/hgrc)|
|Create a branch||tag ; update||-||branch||bookmark|
|Merge a branch||update -j (or checkout -j)||-||merge||merge|
|Change to a branch||checkout||-||checkout||update|
|Revert unregistered change||N/A||svn checkout file||git checkout -- file||update --clean|
|Revert registered change||N/A||revert||git reset HEAD -- file||revert|
|Revert uploaded change||--||--||git revert (makes a new commit to undo the changes)||backout|
So svn update is equivalent to git pull.
Revert unregistered changes is logically not possible: since the file is not tracked, the software does not know its history. Real reverting of uploaded changes is possible, but highly discouraged. Instead, simply create a new commit which undo the changes. If you use git, and did commit the change, but not yet push it, look at git commit --amend or git rebase.
A first check out is pretty simply. For example:
cvs -z3 -d:pserver:firstname.lastname@example.org:/cvsroot/rails co -P 18xx
svn co https://dev.rubyonrails.com/svn/rails/trunk rails
git clone git://github.com/rails/rails.git
In each case, the software will ask for authentication if that is required. Subversion and Git will automatically store this information. CVS does not store this information automatically. You need to explicitly tell CVS to do so using:
cvs -d:pserver:email@example.com:/cvsroot/rails login
Subversion and Git support different protocols, including WebDAV (HTTPS servers). Git and Hg also supports synchronization over SSH (using the "git" protocol). Subversion stores (HTTPS) authentication information in ~/.subversion/auth/svn.simple/ (on Mac OS X, these file only contain a pointer to the KeyChain where the actual password is stored). If git or hg uses SSH, it uses the SSH key in ~/.ssh/id_rsa.
Since the CVS method to store authentication information is a bit complex, here are a few examples.
- Sourceforge anonymous
- -d:pserver:firstname.lastname@example.org:. Password is empty (press enter)
- Sourceforge logged in
- Apple open source
- -d:ext:email@example.com:. Despite that it says "anoncvs" and uses "apsl" as the username, it is not anonymous. You must have a (free) Apple Developer login (ADC account). When logging in, concatenate your username and password like this myusername:password and use this as your CVS password. For example johndoe:verysecret.
Create A New Repository
You can also start your own repository. If you migrate to subversion, have a look at the import commands.
cvs init cvs import
svnadmin create svn import
git init git add
hg init hg add
Create a bare GIT repository
A small rant: git is unable to create a normal bare repository by itself, and push it while it is still empty. Stupid git indeed.
To be precise, it is not possible to clone empty repositories. So an empty repository is a useless repository. Indeed, you normally create an empty repository and immediately fill it:
git init git add .
However, git add is not possible when you create a bare repository:
git --bare init git add .
gives an error "fatal: This operation must be run in a work tree".
You can't check it out either:
Initialized empty Git repository in /home/user/myrepos/.git/ fatal: http://repository.example.org/projects/myrepos.git/info/refs not found: did you run git update-server-info on the server?
git --bare init git update-server-info # this creates the info/refs file chown -R <user>:<group> . # make sure others can update the repository
The solution is to add a file in that repository, and then push it.
git init touch .gitignore git add .gitignore git commit -m "Initial commit" git push <url or path of bare repository> master
Git, WebDAV and hooks
Unlike subversion, Git does not have a dedicated webdav module in Apache. This means that for git, webdav is just a remote filesystem and nothing more. In particular, no scripts are executed after a git push to the server if webdav is used. So it is not possible to send notification emails with git over webdav.
If you really want notification emails, either you have to use another transport facility (e.g. ssh), typically in conjunction with Gitlab software, (see this overview of git protocols). If you must use webdav you have to revert to cron job trickery. If you revert to the cron job trickery, be certain that you clone/pull of the repository and run the scripts in the clone. Do not execute hookup scripts in the main server repository itself: those hook scripts are world-writable using WebDAV, and automatically executing world-writable files is a Very Bad Idea.
Tags, Branches and Trunks
CVS has support for tags and branches.
- A specific version of the repository. Often used to denote a specific release. For example the tag "rel_1_0_3" may be used to indicate exactly which files and which version of these files are included in release version 1.0.3 of a repository with software source code.
- A split-off of the linear software development. A branch deviates from the main code development without affecting it. For example, a repository can have a stable and experimental_feature_X branch, where the later is used for the development of some experimental new feature, without affecting the main development version in the main branch (called the trunk).
- The main branch of a software project.
- merge (verb)
- Branches are typically merged back in (recombined with) the trunk after a new feature is implemented and up to the quality standards of the rest of the project. Merging is a key feature of version control software, but can still be a tedious process.
Only CVS implemented the concepts of tags and branches. Subversion does not support it, and tags and branches are by convention a directory in the repository. Because Subversion support moving and copying of files, the history information for these files is still retained.
To download a specific (tagged) release with CVS:
cvs -z3 -d:pserver:firstname.lastname@example.org:/cvsroot/zeroconf checkout -r rel_0_5_2 -P tmdns
Code:VCS_update lists a small script to update cvs, svn and git repositories.