Version Control Basics

From Exterior Memory
Jump to: navigation, search

This is a basic introduction to Version Control Systems (VCS) such as CVS (Concurrent Versioning System) and SVN (subversion).

VCS Software

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).
GIT
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.
Bazaar
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.

Command overview

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.

Function CVS SVN GIT HG
First download checkout checkout clone clone
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
Upload changes commit commit push push
List current changes status status status status
View changes diff diff diff diff
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.

First Checkout

A first check out is pretty simply. For example:

cvs -z3 -d:pserver:anonymous@rails.cvs.sourceforge.net:/cvsroot/rails co -P 18xx
svn co https://dev.rubyonrails.com/svn/rails/trunk rails
git clone git://github.com/rails/rails.git
hg clone ssh://hg@bitbucket.org/thomthom/solid-inspector

Authentication

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:anonymous@rails.cvs.sourceforge.net:/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:anonymous@cvs.sourceforge.net:. Password is empty (press enter)
Sourceforge logged in
-d:ext:myusername@cvs.sourceforge.net:.
Apple open source
-d:ext:apsl@anoncvs.opensource.apple.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.

tag
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.
branch
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).
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:anonymous@cvs.sourceforge.net:/cvsroot/zeroconf checkout -r rel_0_5_2 -P tmdns

Update Script

Main article: Code:VCS_update

Code:VCS_update lists a small script to update cvs, svn and git repositories.