A composable pijul user interface? (brainstorm)


See the discussion here: https://nest.pijul.com/pijul_org/pijul/discussions/60


For the record, I will now work on pijul command line interface, with the main objective to make it easier to use and more consistent. I have started a repository on the nest to build an empty pijul that would only parse the command line arguments. This can be seen as an attempt to specify the cli before actually implementing it in the upstream.

You are welcome to help in any way. I just read your brainstorm and I think there are some really good idea in it.

I think we should try to specify completely the cli before going any further.


A few things I’ve noted.

Add is obsolete

Needing to pijul add new files is error prone (I for one tend to forget it easily), and not needed often if a good ignore file is in place. record (or whatever its equivalent ends up being named) should offer by default to add any new non-ignored files. To make this acceptable, the dialog when recording the addition of a file needs to offer the following:

  • Add the file
  • Delete the file
  • Add the file to a local ignore list
  • Add the file to the shared ignore list.

With the last two options, the user should be able to edit the ignore pattern before validating.

Push / pull distinction is less important than sync / merge

The distinction between push and pull is not a conceptual distinction, just a change in direction. On the other hand, the distinction between merging two branches (or rather two patchset), and transferring patches between branches needs to be made more overt than it is already. I think the two commands should be:

  • pijul merge [branch] <patchset> offers patches from <patchset> to add to <branch> (presumably defaulting to the current branch)
  • pijul sync <from-repostate> <to-branch> makes the content of <to-branch> (which may be remote) be equal to that of <from-repostate>, presumably requiring an option like --force in case where patches are present in <to-branch> but not in <from-repostate>.

Vocabulary is needed

Pijul needs a good vocabulary to refer to its concepts, a naming scheme and operations on them. Native english-speakers are probably needed here to make the right choices.

  • a patch is […]
  • a patchset is a set of patches. They can be unionned, intersected, filtered by name / tags / author / … and queried for dependencies.
  • a repostate is a set of patches, closed under dependencies. . Their contents can be queried for files: <repostate>/dir/file is the state of that file when the patches in repostate are applied. The difference between two repostates is a patchset. A patchset can be applied to a repostate if all of its dependencies are present there.
  • branches are local labels for repostates; they can be updated and dereferenced. They are referred to by an URI of the form proto://Repo-URL#branch
  • repositories contain several branches. They have an URI.

We may or may not want the notion of remote from git; likewise, we may or may not want a set of draft patches, corresponding to the index in git (i.e., they are given special identifiers preventing them from being referred to in patchsets).


Speaking of push/pull, I’d like to introduce sync/merge/pull/push/clone from/to subfolders of repositories in Pijul 0.9. In order to be efficient, this will require a change in the patch format (which is needed for other reasons, as noted by @lthms when he tried to fix tags), and the promise that we will never want to move stuff between files (conflicts between two moves would not be computationally easy to detect, and would probably be extremely confusing to users).

@flobec, speaking of patchsets and repostates, I think we only want sets of patches closed under dependencies. Your proposed notion of patchsets is simple and minimal, and is the object we transfer over the network, but is likely to be confusing to new users, as they’re not closed under dependencies. This means that a new user would have to understand what a dependency is before understanding that concept, and we might want to avoid that requirement (do we?).


I mostly agree that patchset will not appear too often. They may be
needed if we implement an equivalent of darcs send. They can probably
be given a second-class name like partial repostate to reflect their
second-class citizenship.


0.9 is alrdeay big enough, no? I’d rather test a lot your waited patches and wait for 0.10 to add this feature. What do you think?


I’ve just started to tinker with pijul. Tried it out (but not yet with a real project), read the documentation and skimmed over the paper (my knowledge of category theory is limited, but it’s enough to get the gist I think).

Before I’m to familiar, I’ll try to write down my impressions about the vocabulary and how it matches my mental model.

My mental model is: I can make changes (patches) to a project (repository). A repostate is just starting with nothing and applying a bunch of changes. It’s intuitively clear that changes can or cannot be independent of other changes. Also, the difference between states is also just a set of changes.

I think the biggest stumbling block is to understand what a patch is. I’m not a native speaker, but the metaphor is unclear to me. Imo it makes sense to “patch software”: There is a hole (security vulnerability) and we patch it up (issuing an update that fixes that). But I’m not patching up a project until it’s complete and patches do not really depend on each other. And what is “recording a patch” supposed to mean?
I know that the documentation explains patches as changes on several occasions. But that alone could be a sign that it could be a good idea to call them “changes”, “edits” or something in that direction.

Then, repostate. I find it a little bit clunky, but it’s fairly descriptive. What I don’t understand are branches in that context. In my mental model, a branch is just a point in the development of the project, the application of all changes that lead to that point. So people can branch of from another path of development etc. So, the branchness of a branch is a structural property.
But the defining property of a branch seems to be that is labeled. For me, when a pijul branch is a branch, then repostate must be a branch too.

Little nitpick: I associate the command “record” with “start a recording” while pijul is always recording and the command is ending it. Maybe “report” would be clearer? Idk.

Another nitpick: “blame”. It’s more of a personal thing but for me the snark of the git blame command symbolises everything that is wrong with git. From the hostile community that it came from to the hostile user interface it has.

Just to be clear, my understanding of pijul could be wrong and this is just my impression. Also, naming things is hard :smiley:


You’re absolutely right about patch being standard but misleading terminology. Contribution is a better word to carry the meaning of “unit of work to be shared”. What do others think; should we switch?


For branches versus repostates, it’s a variable versus value thing: at any point in time, the value of a branch is a repostate. If I do, say, a pull operation, then the value of this branch is going to be another repostate. I can’t think of a better word to carry that idea than branch right now, and the word is quite standard, so I think we’re better off keeping even though, as you said, branching is not fundamental to how they’re used. The alternative would be to call them “feeds” or “channels” to carry the idea that you want to watch their contents in order to follow the development of the project.


I like contribution very much. It’s more meaningful and has quite a positive connotation.

Maybe just “tag” or “marker”? But of course branch is standard lingo. I just have the feeling that the name “branch” conveys that it’s more than it’s actually is.


pijul contribute would be kind of long to type. Aside from that, in my post here https://nest.pijul.com/pijul_org/pijul/discussions/60 I was discussing factoring away false semantic distinctions to be made in the UI and using very literal, boring, and straightforward naming. This improves composability, for one.

For recording changes to the repo I might do:

pijul add changes

That means we can do:

pijul remove changes

To unrecord changes.

pijul add files

To add files to repo.

pijul list files

To list files in repo.

pijul list changes

List recorded changes in the repo (aka pijul log)

…and so on.