Darcs

Darcs is a wonderful new revision control system. It’s quite different from CVS or Subversion. First it has no versions, second it’s distributed.

A version control system with no version? Silly me! Of course Darcs has versions, but you’re responsible to create them yourself.

Distributed means, that there is no dedicated central repository. Each repository exists on it’s own, if you’d like to have a central repository where all developers check in and out is up to you.

Darcs is being developed by David Roundy, a physics professor at Berkeley. It’s build upon a “theory of patches”. If this sounds very academic I should mention that it’s programmed in Haskell. But wait! It’s really good, and you don’t have to have several diplomas to understand it. Quite the opposite, it’s really very simple and elegant.

I’m writing this because I couldn’t find a good introduction into Darcs. Funny enough that was my fault, because even if Darcs is an advanced tool it’s surprisingly simple. Anyways I’ll present a quick introduction here, but for a complete reference see it’s manual.

At first I had a list of commands and what they do, but honestly it would not help anyone who knows to read a manual. So I’ll take another approach. I’ll try to cover the common uses of a versioning system and explain how to accomplish that task with Darcs.

What I like about it

Offline usage

You can work on your own repository on your own computer and as soon as you get connectivity, you upload the files to another repository.

Compare that to CVS: You make changes, and check them in with a single command – no distinction between different changes.

Cherry picking

Since Darcs operates on patches you always can choose which ones you check in, or check out. If you and your developers are disciplined enough, you can easily keep multiple branches in sync.

Documentation

Darcs is well documented, and it’s included help system is also very good.

Simple yet powerful

The patch-system of Darcs is very intuitive (really!), and still very powerful.

What I don’t like about it

The community behind Darcs is very able (Darcs is written in Haskell), but limited in size.

Darcs’ tool support (IDE plugins, GUIs, additional Software) is not very extensive. But there are some nice projects, like an Eclipse Plugin, a Web Frontend and even a Trac module.

Installing it on Mac OS X (using DarwinPorts) is easy, but takes forever since it depends on the Glasgow Haskell Compiler which takes a lot of time to compile itself. For Windows and Linux are binaries available. Gabriele Renzi pointed out that there are binaries for Mac OS X available, thanks!

You have to handle the user accounts on your own. Darcs doesn’t have to do anything with permissions. You either handle it via file-system permissions, SSH accounts or something like that.

Creating/Initializing a repository

If you’d like to create a new repository, for a new project, or for an existing — not version controlled project, darcs initialize is your friend.


mkdir ProjectDirectory
cd ProjectDirectory
darcs initialize

This command creates a directory _darcs which contains metadata and your patches, simply said it’s your repository. Please be sure to understand the difference between project files and repository. The repository lies under the _darcs directory and keeps track of the changes etc., the project files are the files you are working on.

Adding files to version control

If you’ve created some files, or would like to import your existing project files, you run darcs add.


darcs add * -r

This command adds all files in the project directory (-r means recursively include subtrees) to your repository. Please note, that your repository is not changed by this command. It only tells Darcs that these files are under version control.

Check what you’ve done since your last “commit”

Often you’d like to see what you’ve done since your last commit, and which files have changed, are new or have been removed.


darcs whatsnew -l

The -l parameter tells Darcs to show a summary, including new files. You’ll see a summary like


M ./modified.txt +1
R ./removed.txt
A ./underversioncontrol.txt
a ./newfile.txt

M… Modified file (showing the changed lines).
R… Removed, file is under version control, but has been removed.
A… Added to the repository.
a… New file, not under version control.

If you ommit the -l parameter, you’re shown the changes within the files in Darcs’ own patch format. You can always get an original diff file out of Darcs if you need one.

Commiting

So far we did not change our repository. To get your current changes into the repository (AKA commit), you simply “record” the changes with darcs record.

Now I have to explain patches. All Darcs operations work on patches. So if you commit something, you commit one or more patches, if you check something out, you check out patches etc.

So, if you call darcs record Darcs will ask you for each change if it should record it. One collection of changes together form a patch.

After you’re done with selecting your changes, you’re asked to give a short patch-name, and a longer patch-description.

If you’re sure that all changes need to be in the repository, you can use -a for all changes to skip the change selection. I usually use darcs record -am 'my meaningful patch name'. This will immediately record (commit) all my changes as a single patch.

Pushing changes to other repositories

As said above, Darcs has no central repository. You can push changes to any repository you’ve got write access to. It’s similar to a check-in in CVS.

So, to push one or more patches to another repository you use darcs push destination. The destination could be locally or via SSH.

Darcs asks for each patch which is not already in the destination repository, so you won’t transfer more data than necessary.


darcs push versioning.company.com:/path/to/your/project

The above command pushes the selected patches via SSH to a remote repository, and applies them immediately.

Now it’s easy to manage multiple branches the same time, just push a single patch to one or more repositories. You won’t have to merge anything, because you keep bugfixes on both, your HEAD repository, and your STABLE repository in sync. But because of Darcs’ innovative patch system even merging is simply, just pick the patches you need, that’s it. (Take that, CVS and SVN!).

Pulling changes from other repositories

Similar to pushing changes to a repository you can also pull them to your local repository. Just think of pulling (checking out) patches from your central repository, or from another branch of your project.


darcs pull versioning.company.com:/path/to/your/project

The above command pulls the selected patches via SSH from a remote repository, and applies them immediately.

With such features it’s very easy to manage multiple branches and versions of your software, or configuration files. Darcs’ manual calls this feature cherry picking.

Checking out a whole repository

To download the whole repository from you could create a new repository and download all patches from the source repository (darcs init followed by darcs pull ....). But there is a much more convenient and faster way:


darcs get versioning.company.com:/path/to/your/project

Notice, Darcs will create the project directory for you, if a directory with the same name already exists, the new one will get a suffix (_0, _1, _2…).

Creating a branch

So I’ve talked about branches earlier, how to we get one? This too is very easy, because you can think of a branch as just another repository of the same project.

So to create a brach you either could get your current repository from your local machine, or put your local repository to your remote machine. Often some computers aren’t accessible from other networks (NAT), so it’s necessary to be able to put them.


darcs put versioning.company.com:/path/to/your/project_STABLE

Again, it’s absolutely not necessary to have the branch on another computer, it’s perfectly good to put them on the same machine.

Creating/Tagging a version

Darcs does not create versions for each patch you record. You have to mark versions yourself. So, to tag the current state of your repository as a version you use darcs tag.


$ darcs tag
What is the version name? Version1
Finished tagging patch 'TAG Version1'

This versions are really what you would expect from versions if you don’t know CVS or SVN.

Sending patches via mail

Especially Open Source projects rely on patches from various people, but are not able to give anyone write access to the source code repository. Darcs enables you to send patches directly via mail instead of writing directly to the repository.

This gives the author of the project the possibility to check your changes and accept them or not.

Darcs needs to compare your local repository with another one (preferably the one you’d like to get your patch in).


darcs send versioning.opensource.org:/path/to/their/project

Again, Darcs will ask you for the changes, and the email address you’d like to send them. The receiver will use darcs apply to apply the patch if it’s good.

Looking at changes

Why use a version control system if you don’t watch your changes? To get a summary of all changes made to the repository you use darcs changes. It gives you a standard changelog you can include in your release notes, or changes.txt.

Assuring quality

Darcs has a lot of options, one of those is the ability to define a test program. This test procedure is being executed every time you record a patch. The patch is only recorded, if the test succeeds (determined via the shell-error codes).

To define a test procedure or test program, you simply type:


darcs setpref test "echo 'you really, really should test your code'"

This is written into your project/_darcs/prefs/prefs file, you can also define a system wide test procedure in ~/.darcs/prefs.

Tests are executed on a special working copy (speak: clean checkout from the repository).

Some advanced operations you might need

If you recorded a bad (buggy) patch, and you’d like to remove it before anything bad happens, you can quickly use darcs rollback. Rollback records an inverted patch, it does not affect your working directory.

If you’d like to physically remove patches from your repository (not working directory), darcs unrecord is just for you. If you’d also like to remove the changes from your working directory you should use darcs unpull, please not that you’ll loose the content of these patches!

If you forgot some change, or found a bug in a previous patch, you can use darcs ammend-record to add changes to the previous patch.

A feature you’re very unlikely to need is darcs trackdown, but it gives a peek view of what Darcs’ simple but powerful patch-system is capable of.

For example search for the patch that changed the password in some file:


darcs trackdown "grep 'adminPassword: admin' configuration.cfg"

Removes a patch after another until the command (grep in this case) returns true. Patches are removed on a special working copy, just like the tests.

Short Reference

This is a very short reference I wrote for myself, the manpage or the manuals does a better job. Maybe you’ll find it useful anyways.

initialize sets the repository up. Can be executed in an empty directory or within your existing project directory.
add adds one or more files to the repository. You can use darcs add * -r to add all files within this and subsequent directories to the repository.
whatsnew shows all changes. You can use the command line switch -l to see a short summary and files which are not in the repository.
record persits the changes to the repository. Each change is a patch of it’s own, so usually you’ll use record very frequently. darcs record -am "comment" applies the same description to all open changes.
changes lists all changes (patches) recorded in this repository.
push sends patches to another repository (local or remote), usually via SSH.
pull gets patches from other repositories (local or remote).
remove removes the file from the repository. Be aware that this will delete the file from remote repositories, but not your working repo.
mv renames or moves a file. Using this command Darcs is able to handle it without losing consistency in other repos.
replace changes tokens within your files. It’s like search and replace, but has some backup built-in.
send packs a set of patches in a file and sends it via mail.
apply takes the set of patches and applies it to the current repository.
get fetches a complete repository (creates a new directory for the repository)
put copies the current repository to another location. Creates a new directory if not already existent, and checks whether it’s “free” (not already a Darcs repository).
tag is used to name the current state of the repository. It’s used to create versions. You can give --tag parameters to get for example to fetch a specific version.
optimize speeds the operations on the repository up. Most useful for remote repositories.
amend-record replaces a previous record with a new one. Has consistency problems and shouldn’t be used all too often.
rollback logically removes the previous patch. Logically: the original patch remains, only a inverse patch is added. Doesn’t affect the working directory.
unrecord physically removes a patch.
revert removes changes made to the working directory. It’ll reflect the state of the repository.
unrevert can undo the last revert.
unpull removes a patch from the repository and from the working directory. Nothing left if you’re the only repository with that patch! (Is like unrecord and revert, just without the unrevert possibility)
annotate gives the complete history of a file or directory.
trackdown iteratively removes the last patch and runs the given command until it returns no more errors. For example darcs trackdown 'grep TODO file.test' returns the last patch that had “TODO” in “file.test”.

Ommited commands: repair, dist, resolve, diff, obliterate, check, setpref. I don’t think they’re important, but as you can see, Darcs isn’t very bloated.

Update: Link to binaries for Mac OS X added.

I should say, one of the motivating factors was the theory of patches, but there was also the feeling that things could be a lot simpler. Physics is all about symmetry, and most of the problems I saw in arch, both in its complexity, and in its behavior, are due to artificially broken symmetries. Developing a more “elegant” system was certainly in my mind.
— David Roundy (Creator of Darcs)One danger that is often mentioned is that of a lack of contributors due to the rarity of Haskell programmers. I’ve been surprised by the number and quality of contributors darcs has had. There seem to be quite a few people out there just looking for somewhere to use Haskell!
— David Roundy

Comments

comments powered by Disqus