Taking version control to the next level.
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
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.
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.
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.
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 * -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
-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.
So far we did not change our repository. To get your current changes into the repository (AKA commit), you simply “record” the changes with
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 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.
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
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.
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.
||sets the repository up. Can be executed in an empty directory or within your existing project directory.|
|| adds one or more files to the repository. You can use
|| shows all changes. You can use the command line switch
|| persits the changes to the repository. Each change is a patch of it’s own, so usually you’ll use
||lists all changes (patches) recorded in this repository.|
||sends patches to another repository (local or remote), usually via SSH.|
||gets patches from other repositories (local or remote).|
||removes the file from the repository. Be aware that this will delete the file from remote repositories, but not your working repo.|
||renames or moves a file. Using this command Darcs is able to handle it without losing consistency in other repos.|
||changes tokens within your files. It’s like search and replace, but has some backup built-in.|
||packs a set of patches in a file and sends it via mail.|
||takes the set of patches and applies it to the current repository.|
||fetches a complete repository (creates a new directory for the repository)|
||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).|
|| is used to name the current state of the repository. It’s used to create versions. You can give
||speeds the operations on the repository up. Most useful for remote repositories.|
||replaces a previous record with a new one. Has consistency problems and shouldn’t be used all too often.|
||logically removes the previous patch. Logically: the original patch remains, only a inverse patch is added. Doesn’t affect the working directory.|
||physically removes a patch.|
||removes changes made to the working directory. It’ll reflect the state of the repository.|
||can undo the last revert.|
||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)|
||gives the complete history of a file or directory.|
|| iteratively removes the last patch and runs the given command until it returns no more errors. For example
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