| jj is truly its own VCS, so to deeply understand it, it's more than short. But it does map to git, and so you can sorta explain it in git terms. It's really kind of like "what if you tried to build hg on top of git?" jj is kind of hard to really explain because a bunch of the design decisions have subtle but important impacts on other decisions, so your first impression of a feature may be slightly wrong because you don't get the implications yet. jj is sort of the same as git: you have a DAG of snapshots of your project. The differences are in how you interact with those things. To try and put it in git terms: 1. Commits are mutable, not immutable (but we'll talk about is more later) 2. You're always working in the context of some commit 3. When you modify a file, it becomes part of that commit (we'll talk about the index in a minute) 4. You don't need to care about branches at all, the "detached head" state is the nrom. 5. commits are immutable in the "immutable data structures" sense, in that whenever you modify them, it's almost like you're adding a commit to them. this is why jj calls its "commits" "changes", change IDs stay stable as you edit them, and they produce new git commits for every edit. 6. Because of how this all fits together, you don't need an explicit index; if you want one, you can just `jj new` twice to get two changes on top of each other, and then edit your files. When you have what you want, `jj squash` will move the diff into the parent commit, and now it's "part of that feature" or whatever. If you want `git add -p`, that's `jj squash -i`. That is kind of it on some level, but in reality, it's kind of hard to convey how a few, smaller, more orthogonal primitives let you do everything you can do in git, but easier. (I tried to actively think of cases last night and only came up with two or three that were easier in git than jj, and jj will have fixes for most of those soonish.) stashing is another great example of a feature of git that's just a workflow pattern in jj. There's just... it's a lot. It's hard to know what the best thing really is. Other than `jj undo` :) (I've got this on the brain since I am literally working on my tutorial right now) |
> it's kind of hard to convey how a few, smaller, more orthogonal primitives let you do everything you can do in git, but easier
Some of this didn't really click for me until I experienced it (and I'm still very much learning). The one that sticks out is how you're always in a commit. Where in git you work in "modes" – editing in the index, rebasing, committing, etc. In jj you're always "stable" and can do anything from that point.
The way this is sold is things like "mutable commits" or "first class conflicts", but for me the real power was just realising that I can always move to another commit/change without having to pre-plan how to do that, always being able to edit my commit message right now without having to finish up something else first. Now going back to git feels like the tool is slowing me down and not keeping up with the pace and style I want to work in. I was surprised that this was the thing I most enjoy, because it's a little hard to motivate.