Pijul

Pijul as first version control system

Hi people!

I have no experience using a version control system. I read a fair bit about pijul, and I would like to learn that without having experience with Git. Would that work? Where to start?

I see there is a whole range of Git tutorials for beginners. If I start with that, do I learn the concepts wrong, and do I need to re-learn when coming to Pijul? Or can that be mitigated by skipping certain parts (which?)? Or is there some tutorial for Pijul, not assuming prior knowledge of a VCS?

thanks!

1 Like

I don’t think there would be anything wrong about learning Pijul as your first VCS. The concepts are radically different from Git’s, and most of the time much much simpler. To begin with, you don’t need to understand how things work under the hood in order to use it, you only have to understand what patches are. Then, working with Pijul means producing and exchanging patches, that’s all.

One difficulty I can see is that while Pijul’s concepts are simpler, the community is many times smaller, and questions you may have may not be readily solved on stackoverflow. That said, you are also likely to have way less questions.

I think the manual is a bit sparse, but it does list all the commands (which you can get from using pijul help anyway).
There is still a mixture of referring to “patches” and “changes” since the terminology was changed in the code…

If you do read about Git, or other VCS except Darcs, you will think of it as a way to capture snapshots of files. But Darcs (maybe SVN) and Pijul accumulate sets of changes to files. It’s almost the same thing, but not quite. Someone correct this if it’s wrong:
The biggest difference is that snapshots are derived from a parent in a linear fashion, whereas sets can have multiple dependencies. This affects how the tool can determine conflicts and report on the history.

For someone just starting out, I would suggest this comparison of concepts. It’s an old article, but it’s good. The tutorial it points to at the end is specific to one tool, but it’s also very good at showing how to use version control in general. I hope to have a similar tutorial using Pijul, one of these days.

1 Like

The article you link to, seems to speak about branches and snapshots: concepts that I am beginning to suspect are not applicable to Pijul. The list of Pijul commands is a nice reference, but feels like phase 2 in the learning.
I am actually looking for a conceptual overview, like ‘what is version control’ but then with just Pijul concepts.

If I understand @pmeunier (wow the man himself answered! proud…) correctly, the concept of patches is the most important one. But I think I should still understand repository, staging, and whatever more there is.

Thanks for both your input, I’ll see what I can find out. And if there is no real beginner tutorial I might be learning the wrong things first and maybe that is not so bad after all :slight_smile:

No, those concepts are in the mental model that a person has when using the tool. Most people think of the different versions (like releases) as snapshots that are held in various branches (on the collaborators computers perhaps). The various tools fit the mental model to different degrees. I personally have a hard time with Pijul. It feels cumbersome and obtuse. I have no idea which changes are where and it isn’t very good at telling me. It shows the huge hash ID instead of something I can relate to like the message used when recording a change. Channels are some mysterious things that seem similar to Git branches, but supposedly are not.

Those two articles give quite a lot about version control concepts. There isn’t a Pijul version since the software itself is still alpha. There might be a Darcs article. (Pijul is very similar to Darcs.)

Those topics would vary depending on the tool you choose.

Let me try to explain a very simple list of basic definitions, in the order you are likely to use them:

  • pijul init creates a “repository”, which you can see as an archive of all the changes you have applied to your project since the beginning, along with a list of files that Pijul is currently interested in.
  • pijul add Cargo.toml src/lib.rs would be the command I run if I want to let Pijul know that I want to track the two files named Cargo.toml and src/lib.rs. If you have many more files to add, see pijul add --help.
  • Then, pijul record will create a change (also called a patch) and apply it to the repository. That command will ask you to create a signing key with pijul key generate. Patches are signed by default in Pijul (this isn’t enforced very well at the moment, the Nest doesn’t show the validation, for example).
  • See what you’ve done: pijul log and pijul change are probably your next steps.
  • Changes are the central concept in Pijul. You can push them to the Nest: if you have created a repository called foo in your account (let’s say Justin is your login), you can do pijul push Justin@ssh.pijul.com/foo to push your change there. This requires you to have uploaded your SSH public key first.

The next useful command you might need is pijul unrecord, which actually “unapplies” rather than “unrecords” patches, since your patch still exists in .pijul/changes after that.

As @joyously said, we also have a slightly confusing concept called “channels”. A channel is a name associated to an evolving set of patches. I personally don’t use them very often in public. They took me a significant effort to implement, as I had to write an entire database backend from scratch in order just to implement them. I initially wrote them to make it easier to Git user to start understand why they don’t need them (like “I’m not telling you patches are better than branches because I can’t have them, but rather because patches actually are better”). Here are two ways in which I found channels useful:

  • In Rust, when I wanted to maintain versions of Thrussh (my SSH library) compatible with multiple versions of Tokio (while the Tokio ecosystem was transitioning to 1.0), and apply the same patches to both versions.
  • There are times where I want to prepare a complicated patch, or squash multiple patches together, or review a patch submitted on the Nest. In these cases, I often find that forking my main channel temporarily makes the operation easier.

Channels are a different from Git branches in multiple ways, the main one being that you can’t merge channels, whereas merging branches is the primary way through which a Git project progresses. While Git has many commands to deal with branches and try to simulate patch commutation, Pijul can deal with all that complexity (and more) by just applying and unapplying patches.

Most uses of Git branches are just patches in Pijul, since branches are usually meant to keep different features separate, merge them, and push them independently.

Squashing patches and selecting what to make into a patch are still topics that bother me a lot.

Could you please elaborate how you do that practically? Suppose, you receive a channel with a mixed set of patches (i.e. not all of the concern you). How do you effectively identify and select the right ones, so you can squash them?

I would fork the channel pijul fork tmp, then pijul channel switch tmp, and then unrecord the changes I’m not interested in (by running pijul log to select them, and pijul unrecord). Then, I would do a pijul reset -a in order to get rid of the modifications in the working copy that were introduced by these patches I just unrecorded.

Finally, I would unrecord the patches I want to squash, and record them again with pijul record.

If the patches you’re not interested in do not depend on the patches you want to squash, you don’t have to unrecord the patches you’re not interested in.

I realise this could be turned into an easier command to do all these steps on its own. Maybe an external script called pijul squash?

Yes, some interface, like git rebase --interactive, might be appropriate. One would likely want to see an editable list of changes and drop unnecessary ones and select others for squashing.

Is it possible to split a change in two when it concerns two locations inside a single file? Can I record only one out of two hunks of a file? I tried that 2 months ago and weren’t successful.