Hi there! I’m looking into Pijul, mostly out of curiousity, and wondering how to accomplish the equivalent of checking out an old Git commit.
Say, for example, I notice compile times have drastically increased at some point, and I want to find out which patch caused it (possibly by bisecting). How would I accomplish that in Pijul?
Hi! thanks for your interest. We don’t have bisecting yet, but the way Pijul works is quite different from Git, you would have to unrecord individual patches in order to get back to a previous state.
The current way to do this is by (1) branching, in order to keep your current state, and (2) on the new branch, unrecording the patch you think might be causing the problem, then reverting to get the working copy back to that state.
This is all kind of tedious as of now, because only primitive operations are implemented, but we’d be delighted to hear feedback about how to make it easier. In particular, maybe there are easier workflows than bisect (Git does it because history in Git is sequential, we don’t have that restriction here).
I’ve been thinking about this too. Bisect is nice because often I don’t actually know what caused problems, so I say, let’s try to go completely back in time at X and see if it worked correctly back then. While this is would be possible in pijul too with the implementation I suggest, pijul’s model might lend itself to some interesting applications: say that now I found an untested bug; I don’t know what commit caused it yet, but I know how to test for it; so I commit a patch with the new test, then roll back each previous commit (leaving the new test applied), each time testing the repo against the new test (and it should be simple to make it automatic, say pijul bisect --exec "./my_testsuite"). This would be very cool and impossible with snapshot-based vcs, because those are roll-all-or-nothing.
Maybe the bisect command would be something like: pick the patches I want to unapply from a date-sorted list (for convenience + preserving git’s functionality); I can pick both item-by-item and by range (1, 3, 6-15). Interactive selection by default, but also scriptable. Optionally declare one or more commands to execute at each unapply event.
My main point is that if the testing is automatic we get rid of all the annoying manual fiddling (git start then git bisect than again than remember to clean up, etc).
This would also mean getting rid of the gradual halving algorithm; we can actually test all the patches we want, as it comes to little cost (unless the test takes a lot to run), than return a list of all failing patches, sorted meaningfully to help us catch the bug.
Thanks for that solution, even if it is currently a little manual.
Plus the alternative to bisecting there is a really cool idea.
Perhaps I distracted a little from my point though by bringing up bisecting. A more important requirement for me is being able to rewind to any previous state of the repo non-destructively. I realize that’s a very linear way of looking it at things, but it’s also important for reproducing the exact environment of a bug/degradation/etc.
So say every patch triggers a build on CI. Would it be best to create branches on every deploy to permit resetting to there?
Good question, it all depends on what you’re doing. Branches in Pijul are not meant to be used like in Git, in fact Git branches are more like patches in Pijul.
A branch in Pijul is a set of patch hashes, plus a representation of the repository state. That internal representation can be a little expensive in terms of space, but different branches share the parts of that they have in common.
So, if you have a branch, outputting its state to the working copy (using pijul revert) can be done in time linear in the size of the working copy. If you want to unrecord a patch, it’s more expensive: unrecording a single patch is linear in the size of the patch, and in the number of lines deleted by other patches around hunks deleted by this patch (this can be large).
Note that there is a way now to do it, to some extent. You can use pijul fork with a patch hash, and it will build a new branch with just that this patches and all of its dependencies. Combined with tags, this gives you what you want (although not as precisely and systematically as git)
This is something that I think is missing in the help and the manual. At least I cannot find it or I’m misinterpreting you: after I create a tag I can recover that state, right? Which command does that?
A piece of git porcelain missing here is the HEAD, as distinct from a “branch checkout”. A detached HEAD is a state where you’re browsing history without the intent of checkouts or even commits ending up on any particular named branch.
(Frustratingly, in git the most common way to end up in one is to try to checkout a remote branch, where “make a local copy” would be a more reasonable default; a remote branch of course being by definition a read-only reference you cannot locally modify. When you explicitly check out a point in history, however, detached-HEAD semantics are in fact desirable)
On a related note, does pijul have any analogue of the git reflog? An append-only meta-history log of what branches have pointed to(and via HEAD, which ones you have had checked out) seems only more vital in a system where branches do not encode discrete sequences of past states.
pijul fork --change <hash of the tag> <name of the branch>
I tried that, but then after pijul channel switch <name of the branch> it crashed.
It left the directory in the same state, hence pijul diff shows all diff between the pointed change and the current state. It wasn’t what I expected, but I guess this is due to the crash.
Another thing I wanted to say about this: tags aren’t working at the moment, and that’s intentional. They depend on the ongoing rewrite of the backend, because they share some of its format, and while I don’t mind breaking the repository format (it’s annoying for everybody, and about 400 times more annoying for me, because I have to convert all of nest.pijul.com in addition to my own repos), I don’t ever want to change the patch format again.
The only reason I’d change the patch format is to introduce a new feature that cannot be foreseen yet (even code movements might be able to use the current format).
pijul channel switch is an alias to pijul reset --channel. I find the latter more intuitive, but we decided to add the alias to make the pijul channel command more complete.