pijul_org / pijul

#327 tutorial

Opened by fedorg, on November 12, 2018
Open
fedorg commented on November 12, 2018

Hi. I've been checking out pijul for a couple of months and trying to find a decent git-centric tutorial online, but that process takes longer that necessary. I have learned about this VCS through a HN post, searched for quickstart docs and eventually gave up (like many). https://jneem.github.io/pijul/ was about the only link that I've come across that actually lists a rather tiny command sequence for a simple workflow without much explanation in the way of what each line does. I can see people using this new VCS, but the general process is not that straightforward for a newcomer. I understand that this is alpha software, but the adoption is greatly hindered by the absence of beginner-level tutorial IMO. If you could provide me with some basic links/pointers to the code, I might compose something myself and put it out there. As it stands today, the code is largely unmaintained and definitely not in the active development process. I hope we could reverse the current course of action by bringing in new folk.

pmeunier commented on November 12, 2018

Hi! Thanks a lot for this proposal. One issue we have with the codebase is that Pijul is a much larger project than initially envisioned. I've had to write two major crates: an SSH library (Thrussh), a database backend (Sanakirja), as well as a number of other smaller crates and libraries. I think the best way to operate here is that you keep asking questions (this page is a rather efficient to keep track of them).

The user interface of Pijul is meant to be extremely simple. As Joe Neeman described, when using Pijul, we're "just" collaboratively editing a data structure by writing text in files. We "record" patches (using pijul record) and send them to each other (with pijul push and pijul pull).

There are a few rules:

  • patches produced independently always commute.
  • patches that touch parts of files separated by at least one line always commute.

A branch is just a set of patches, branches are not as useful as in Git (where they're used to simulate commutation). There's no rebase (we don't need it), no cherrypick (it's the default behaviour), and conflicts are handled by the datastructure itself instead of being an exceptional case of a "failed" merge.

pmeunier commented on November 12, 2018

I should add that the code is not as modular as one would like it to be. This is because "record", which you want to learn to understand what patches are, needs to:

  • output a repository, in order to compare it with the working copy. This is not super easy to do.
  • compute a patch, which is tricky if the output has conflicts.
  • apply the patch to the repository.
  • "unrecord" stuff, in order to provide interactivity.

Maybe pijul apply is a more "atomic" command, but is not meant to be used by the user directly. Pull and push use network protocols (SSH and HTTP), but other than that are probably not too hard to understand. pijul revert -a (akin to git reset --hard) is also not too hard (but the more general pijul revert needs to unrecord stuff). pijul unrecord (which undoes pijul record) might be the hardest command to understand.

Also, the code is split into a command-line interface (the pijul crate) and a library (libpijul). Not everyone agrees on the boundary here, but I'm pretty happy about it. Libpijul contains essentially theory (and all the theory), while pijul contains code that interacts with the network, the terminal, etc.

fedorg commented on November 12, 2018

Wow, that was quick :) Thanks for a very timely response, @pmeunier!

The thing that prompted me to write this was my apparent misunderstanding of pijul revert -a. As you've noted, it should act more or less like git reset --hard. But that raises two questions: what's the equivalent of a working copy - is it a branch, or maybe something else called pristine? How do I reset the working copy to a known state? git reset accepts a commit hash as an input, but pijul revert only works on branches, so how do temporarily revert the working copy to some previous state that is known to compile :) ? AFAIK, pijul unrecord is destructive, so it's not intended to work that way.

Again, thank you for answering. I hope this thread could give everyone enough context or be a pijul for dummies type thread.

pmeunier commented on November 12, 2018

what's the equivalent of a working copy - is it a branch, or maybe something else called pristine?

I'm not sure I understand the question. In Pijul, information is stored in three different places:

  • The working copy, which is a collection of files editable by the user.
  • The patches, in .pijul/patches.
  • The pristine, in .pijul/pristine, which contains all the branches in a binary representation.

From the user's perspective a "branch" behaves like a set of patches. However, this can be very inefficient if implemented with patches only (like in Darcs, for instance). Therefore, Pijul uses sort of a "cache" of the current state of a branch, which makes things efficient.

We don't yet have the interface to go back to a particular state. There are two issues:

  • Pijul is much more asynchronous than Git is. Anyone can create patches in parallel, and all patches commute. This makes it much simpler to use for most operations, but complicates the creation of hashes for versions, because "A, B" and "B, A" are the same state. We'd need a commutative hash function (I have one) that can be reverted to turn a hash into a set of patches (I don't know how to do this).

  • Reverting to a version is expected to be less efficient than Git (because you'd need to apply and unrecord patches) in the general case. One way to mitigate this is to store "important" states (such as tags) as branches, which is sort of what Git does. But this would probably have a cost in terms of disk space.