I've been using jj daily for close to a year and without a doubt, it blows the Git UX out of the water. I'm very particular about breaking up my changes into atomic commits, so a killer feature for me is automatic rebasing. Since conflicts can be recorded in commits, you never have to stop a rebase to fix conflicts like you do in Git and Mercurial - history operations work exactly the way a human would expect. Modify a commit? Delete it altogether? jj just automatically rebases all of the descendants for you (and yes, it handles multiple children like Mercurial evolve and unlike Git rebase).
On top of this is a great set of primitives for manipulating commit history - `jj move|restore` to move|copy changes from one commit to another, `jj split` to break up commits, `jj rebase` to move commits around. _Everything_ is inside commit history (no "worktree", no "index"), so one set of commands and flags will do everything you want.
The operation log is also incredible. Most operations can be undone with zero problems. Compare that to Git, where your best hope to fix a bad rebase/commit --amend is to scrounge around the reflog for the right commits and manually fixing up your refs.
The biggest pain points for me are:
- Automatic working copy commit sometimes tries to commit things I don't want. Usually .gitignore has things covered, but sometimes moving files around and rebasing commits breaks things. Fixing up broken commits with `jj split|restore` is pretty easy though.
- No rename detection. jj doesn't handle merges as elegantly as Git. jj devs are thinking about this, but haven't quite cracked it. I'm not sure how long that will take.
On top of this is a great set of primitives for manipulating commit history - `jj move|restore` to move|copy changes from one commit to another, `jj split` to break up commits, `jj rebase` to move commits around. _Everything_ is inside commit history (no "worktree", no "index"), so one set of commands and flags will do everything you want.
The operation log is also incredible. Most operations can be undone with zero problems. Compare that to Git, where your best hope to fix a bad rebase/commit --amend is to scrounge around the reflog for the right commits and manually fixing up your refs.
The biggest pain points for me are:
- Automatic working copy commit sometimes tries to commit things I don't want. Usually .gitignore has things covered, but sometimes moving files around and rebasing commits breaks things. Fixing up broken commits with `jj split|restore` is pretty easy though.
- No rename detection. jj doesn't handle merges as elegantly as Git. jj devs are thinking about this, but haven't quite cracked it. I'm not sure how long that will take.