I think Pijul has some good ideas, but I’m afraid the network effect of git at this point is too strong.
I think jj’s concept of being a front end for many backends and sharing a common UX over them is a good one, but without a pijul backend for existing tools I have a hard time seeing it catch on.
I like the idea of Pijul, and checked it out a couple of years ago. Some basic quality of life features were missing, and are still missing.
For example, diffs can't show context. They show lines removed and added, but can't show the previous and following line because of implementation details.
Pijul seems great and I really want it to flourish. I love reading the blog posts when there are major updates, and its approach seems fundamentally more right than Git's (as it should— while it gets its core theory elsewhere, its UX learns from Git pain).
What I'm waiting for before I switch is mainly a really good bridge to Git. At the first couple tech companies I worked at, I led efforts to switch from Subversion to Git, and I did it by experimenting and I eventually proving a viable path using Git's built-in, two-way SVN bridge, which is excellent.
Whenever I revisit Pijul, I play with importing a giant (pathological, tbh) Git repository. Unfortunately, it runs for days and has never successfully completed for me. But the moment that bridge is good enough, I'm in! (Performance is nice but reliability is obviously the essential thing, especially when it comes to one-time operations like the initial import.)
PS: pmeunier, if you're reading this: I love your work. When Pijul can reliably import Nixpkgs, write a killer blog post about it. I'm sure it'll blow up here on HN. :)
And thanks for your work to advance the state of the art in DVCS! :)
PPS: I wonder if Pijul's fundamentally better merging behavior could become especially salient for teams (or individuals) whose codebases are seeing a lot of churn with heavy LLM use, so that it can help make automatic resolution of merge queues cheaper or easier or more reliable.
Last I tried to run Pijul (IIRC, 2.5yrs ago), there were major, seemingly unresolvable crashes for the simplest of operations on Mac and Linux. Has it gotten better?
> In Pijul, independent changes can be applied in any order without changing the result or the version's identifier. This makes Pijul significantly simpler than workflows using git rebase or hg transplant. Pijul has a branch-like feature called "channels", but these are not as important as in other systems. For example, so-called feature branches are often just changes in Pijul. Keeping your history clean is the default.
This is a useless property because the graph is only encoded at the patch layer. In the real world you have far more semantic dependencies than patch dependencies. ie, I have a patch that adds a function that calls a function added in another patch. Pijul doesn't know about that.
> Merge correctness
> Pijul guarantees a number of strong properties on merges. The most important one is that the order between lines is always preserved. This is unlike 3-way merge, which may sometimes shuffle lines around. When the order is unknown (for example in the case of concurrent edits), this is a conflict, which contrasts with systems with "automatic" or "no conflicts" merges.
I can't remember being bitten by this, and you don't need Pijul to solve this. A merge algorithm that leverages git blame information would work just as well. It's just nobody cares enough to use such a thing.
> First-class conflicts
> In Pijul, conflicts are not modelled as a "failure to merge", but rather as the standard case. Specifically, conflicts happen between two changes, and are solved by one change. The resolution change solves the conflict between the same two changes, no matter if other changes have been made concurrently. Once solved, conflicts never come back.
Conflicts coming back is not an issue in git. For some reason people think they need to use rebase when they should almost always be using merge.
> Partial clones
> Commutation makes it possible to clone only a small subset of a repository: indeed, one can only apply the changes related to that subset. Working on a partial clone produces changes that can readily be sent to the large repository.
Git and other snapshot-based SCMs do this far far better. Git can checkout only a set of files or directories, and the tree-structure encoded in git objects in its db makes this very efficient. You could even build a fuse layer to lazily fetch content. With Pijul you would have to extremely carefully maintain your history to allow this. ie, when you have a patch that modifies 2 other patches, then those are merged forever if you need the changes in the merger. Imagine a PR that reformatted all files in the repo or changes a top level interface and fixed all users in the same PR. Whoops, everything is now interdependent, no more partial clones.
30 comments
I think jj’s concept of being a front end for many backends and sharing a common UX over them is a good one, but without a pijul backend for existing tools I have a hard time seeing it catch on.
For example, diffs can't show context. They show lines removed and added, but can't show the previous and following line because of implementation details.
Here's a diff: https://nest.pijul.com/pijul/pijul/changes/OMGL7JBCLSHWTIYP7...
It's a little thing, but when looking at a diff, seeing three lines of context helps enormously.
https://docs.rs/sanakirja/latest/sanakirja/
https://pijul.org/posts/2021-02-06-rethinking-sanakirja/
What I'm waiting for before I switch is mainly a really good bridge to Git. At the first couple tech companies I worked at, I led efforts to switch from Subversion to Git, and I did it by experimenting and I eventually proving a viable path using Git's built-in, two-way SVN bridge, which is excellent.
Whenever I revisit Pijul, I play with importing a giant (pathological, tbh) Git repository. Unfortunately, it runs for days and has never successfully completed for me. But the moment that bridge is good enough, I'm in! (Performance is nice but reliability is obviously the essential thing, especially when it comes to one-time operations like the initial import.)
PS: pmeunier, if you're reading this: I love your work. When Pijul can reliably import Nixpkgs, write a killer blog post about it. I'm sure it'll blow up here on HN. :)
And thanks for your work to advance the state of the art in DVCS! :)
PPS: I wonder if Pijul's fundamentally better merging behavior could become especially salient for teams (or individuals) whose codebases are seeing a lot of churn with heavy LLM use, so that it can help make automatic resolution of merge queues cheaper or easier or more reliable.
Jujutsu steals it, though! You should probably give it a look.
> Why?
> Commutation
> In Pijul, independent changes can be applied in any order without changing the result or the version's identifier. This makes Pijul significantly simpler than workflows using git rebase or hg transplant. Pijul has a branch-like feature called "channels", but these are not as important as in other systems. For example, so-called feature branches are often just changes in Pijul. Keeping your history clean is the default.
This is a useless property because the graph is only encoded at the patch layer. In the real world you have far more semantic dependencies than patch dependencies. ie, I have a patch that adds a function that calls a function added in another patch. Pijul doesn't know about that.
> Merge correctness
> Pijul guarantees a number of strong properties on merges. The most important one is that the order between lines is always preserved. This is unlike 3-way merge, which may sometimes shuffle lines around. When the order is unknown (for example in the case of concurrent edits), this is a conflict, which contrasts with systems with "automatic" or "no conflicts" merges.
I can't remember being bitten by this, and you don't need Pijul to solve this. A merge algorithm that leverages
git blameinformation would work just as well. It's just nobody cares enough to use such a thing.> First-class conflicts
> In Pijul, conflicts are not modelled as a "failure to merge", but rather as the standard case. Specifically, conflicts happen between two changes, and are solved by one change. The resolution change solves the conflict between the same two changes, no matter if other changes have been made concurrently. Once solved, conflicts never come back.
Conflicts coming back is not an issue in git. For some reason people think they need to use rebase when they should almost always be using merge.
> Partial clones
> Commutation makes it possible to clone only a small subset of a repository: indeed, one can only apply the changes related to that subset. Working on a partial clone produces changes that can readily be sent to the large repository.
Git and other snapshot-based SCMs do this far far better. Git can checkout only a set of files or directories, and the tree-structure encoded in git objects in its db makes this very efficient. You could even build a fuse layer to lazily fetch content. With Pijul you would have to extremely carefully maintain your history to allow this. ie, when you have a patch that modifies 2 other patches, then those are merged forever if you need the changes in the merger. Imagine a PR that reformatted all files in the repo or changes a top level interface and fixed all users in the same PR. Whoops, everything is now interdependent, no more partial clones.