But in short, it has a better UX than Git by a mile while remaining interoperable at the storage level, so you can use GitHub; it has many of the niceties of Mercurial's UX like revsets, no staging area, and a templating language for log output. Conflict resolution and rebasing is clean, easy, and nearly automatic. It has features neither support, like a real undo command and "operation log"[1]. The UX is smaller and conceptually cleaner; fewer "verbs" that operate on less "nouns", so many things are more regular. It is available as an API (Rust crates) so you can extend it naturally to handle your own workflow, without monkey-patching things. You could even use Mercurial itself as a storage backend, or a custom, centralized server like Google does.
Most importantly though, its internal "automatic snapshot model" design is quite elegant and makes the design and internals very clear. And storage system is completely independent and abstracted from this, and many of the other algorithmic details (Git sort of intertwines the data model, the algorithms, and the UX in various ways.) Features like hg changeset evolution, git rerere, and rebase --update-refs are all obsoleted and naturally handled by this design, among other things.
Martin, the lead developer, also had a talk at Git Merge 2022 that covers many of the fundamentals. They're all still the same but we're evolving many things rapidly: https://www.youtube.com/watch?v=bx_LGilOuE4
[1] Yes I know about the reflog, no it is not equivalent! It only tracks changes made to visible references ("ref" "log") while jj's oplog actually tracks commands invoked, and lets you completely undo individual things in the blink of an eye, or rewind if you wish.
Is there anything in jj that could be used as a substitute?
Similarly, there is no concept of stash. The working-copy-commit model removes the need for a distinct "stash" verb, just like it removes the need for the "index" noun.
(In Git, stashes and the staging area are of course trees of blobs, just like ordinary commits. It's just that the UI surfaces them as distinct nouns.)
> This sounds reasonable but I'd like to somehow distinguish these work-on-progress commits. Is there an equivalent of mercurial commit phases?
There isn't any current notion of phases right now, but we've thought of adding them. At the moment, the main distinction added recently is between "immutable" commits and mutable ones, which is determined by a revset, and that revset by default is something like "Anything published on or an ancestor of a head in the remote." Immutable commits cannot be rewritten to a new commit ID.
Frankly I just tag all of my work-in-progress commits with 'wip:', and I use a revset to select and look through every change authored by me that isn't located in the remote main branch.
We are also thinking about improving the color and iconography of the default output to make immutable vs mutable more distinct. So we're not sure if we even need phases yet, I think...
But what I'm most interested in exploring is support for first-class conflicts. I hate the weird state of existing git conflict resolution.