Given my interest in version control, a post on Pijul was pretty much inevitable. The thing I most wanted to understand was of course its conflict resolution algorithm. Unfortunately I don’t know enough category theory for that, which is a novel problem to have at least. There also don’t seem to exist explanations of how this algorithm works that don’t rely on category theory, which is unfortunate. The documentation that exists for this tool is generally sparse, which is fine; it’s new software, after all, and these are alpha releases.

Fortunately, according to their blog, there’s been a useful version released recently. So what follows are my thoughts on playing with that version (0.4.1).

First important thing is that the Pijul repository is itself kept in pijul. There’s a GitHub repository that has all the trappings of being an official mirror, but it looks to have stopped working when they switched the pijul repository off of darcs. To resolve the bootstrapping problem, I installed it with cargo instead, which took a short seven minutes to download and compile everything and dependencies. (Peeking behind my curtain slightly, I tried to write this post both Friday and yesterday, but was unable to do so because their hosting (Nest) was down.)

The next logical thing to do, once the tool is installed, is to clone a repository and play with it. I chose the pijul repository itself on the theory that it would be fairly sizeable and that I wanted to browse it anyway. Unfortunately, they seem to reset their history; there are only about nine commits lying around, one of which seems to be a squashed “reboot” commit. (This is apparently due to some one-time changes to the internal store that coincided with the 0.4 release.)

Several commands share a name with verbs from Git - add, clone, init, pull, push, status - and all seem to present a similar interface (though of course less cluttered). I recognize a few verbs from Darcs as well - record, revert, unrecord, and maybe some others. There’s in-repo branching already, which gives it a leg up on Darcs and Bazaar, neither of which ever got that far. And many other things, as one would expect. I think the most interesting part is that they almost-accidentally baked in a Pull Request model: you just push to a remote, and it makes a listing of patches that can be pulled in later. I think it’s a neat approach, at least, and it seems to integrate well with Nest (their web interface).

merges?

Yeah okay let’s talk about this. The way a repository is presented doesn’t have a notion of history in the traditional sense. Instead, dependencies between patches are tracked, and then each branch has a notion of what patches it contains. So when I pijul record a new commit, the location it shows up in pijul changes is undexpected - often not near the top or the bottom of the list. (I also wish there were more whitespace in its output, but details.)

Now, because their internal patch format is not the traditional Diff-style, there doesn’t seem to be an easy way to figure out what changed in a given patch (yes, this nomenclature is confusing; I’ll try to use “Diff” for the expected thing, and “patch” for Pijul’s base object). I can output patch objects, which is kind of cool, but I don’t see a way to turn these into something I can look at. pijul status also reflects this: it shows the changes currently not associated with a patch, but not in a Diff format.

Anyway, I don’t totally have a feel for this interface, so everything comes off a bit clunky, but I did manage to play with making some of my own patches. An important thing is that I don’t understand the failure mode for its conflict resolution - I applied two explicitly conflicting patches to see what it would do, and it gave me a file that looked like this

prelude
line from patch I applied first
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
line from patch I applied second
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
rest of file

which is of course familiar from git-land, but there’s no indication that it did this - nothing in pijul status or anywhere else I can find. I assume then that Pijul is both aware of the conflict and able to detect this in files, but I do wonder what would happen if I needed to put a bunch of “>” and “<” in a file like that.

Beyond that: merging seems good, it’s fast, and it seems to be able to handle badmerge correctly.

I’m excited to see what happens in the future, but this doesn’t really merit the “usable” label its authors applied. This is general problem I’m finding with Rust and the Rust ecosystem, though: many projects technically work, but aren’t polished or really done to the point where one wants to use them. For this one in particular, no one else seems to know how to use it either (searching for Pijul tutorials got me nowhere, but it did get me a surprising number of articles hyping it as a git-killer without explaining it very much).