What I mean by simpler is, there's fewer features, which makes things easier to pick up, because these features fit together in a way that's more coherent than git's. By more powerful, I mean jj lets me regularly do things that are possible, but annoying and/or difficult in git.
I loved git. I was never the kind of person who thought its CLI was bad. But then, when I found jj, I realized why people thought that.
Makes sense. Developers I know have been wanting that.
The auto-commit behavior was one of my biggest concerns when starting, but it turns out that when combined with other things, I'm a huge fan now, for example.
It does this by adding an new operation on top of the operation log[1], so you don't lose repository states by moving up + down the op log. There's a corresponding `jj redo` as well.
0: https://jj-vcs.github.io/jj/latest/cli-reference/#jj-undo
The biggest issue for me is it requires active change management (or feels like it). In git I do `git checkout foo` then I start editing. If I want to see what may changes are since foo then `git diff` tells me. With jj though, `jj edit foo` is the to git, state of the repo ALL changes to foo. So any new edits are invisible. So, instead of `jj edit` I have to do `jj edit` `jj new`, then later squash those into foo
I know there are similar cases in git but I guess I'm just used to git so I wasn't using those cases.
that said, I'm mostly enjoying jj. Though quite often i get a conflict I don't understand. Today I got 2 and it told me choose A or B. I did `jj diff -r A -r B` and it said no diffs. If no diffs aren't there no conflicts? I'm sure someone gets it but it was annoying to just have to pick one to abandon
For what it's worth, this changed in v0.33.0:
> jj undo is now sequential: invoking it multiple times in sequence repeatedly undoes actions in the operation log.
(release notes: https://github.com/jj-vcs/jj/releases/tag/v0.33.0)
I’m not sure what happened in your conflict situation either, that does sound frustrating. EDIT: Oh, I wonder if it was this: https://jj-vcs.github.io/jj/latest/technical/concurrency/ specifically, that I bet the repo was being modified concurrently, and so you ended up with a divergent change.
You can as of v0.33.0[0]. Previous behaviour was that `jj undo; jj undo` would leave you where you started (it undid the undo).
> The biggest issue for me is it requires active change management (or feels like it). In git I do `git checkout foo` then I start editing. If I want to see what may changes are since foo then `git diff` tells me. With jj though, `jj edit foo` is the to git, state of the repo ALL changes to foo. So any new edits are invisible. So, instead of `jj edit` I have to do `jj edit` `jj new`, then later squash those into foo
I'm not 100% clear on what you mean here, but a few things that might help:
1. In jj you don't "checkout" a branch, you edit a specific commit. That commit might be pointed to by a bookmark but it doesn't have to be. A jj bookmark is roughly equivalent to what git calls a branch. Note that a git branch, and a jj bookmark are just pointers to a commit, as illustrated here[1]).
2. If you want to resume work on a branch/bookmark instead of `git checkout BRANCHNAME` you'd do `jj new BRANCHNAME` which puts a new commit on top of the commit and sets it as a working copy.
3. Bookmarks don't auto advance like they do in git. So adding new commits on top of a "branch" will leave the bookmark where it is until you `jj bookmark set/move` it. So you could squash commits down into the "foo" bookmark, but you could also move "foo" to point to subsequent commits.
4. Not sure what you mean by edits being invisible, but if it's seeing a diff from main to the tip of your branch (with a change id of ex. XYZ) it would be `jj diff -f main -t XYZ`.
0: https://github.com/jj-vcs/jj/blob/main/CHANGELOG.md#0330---2...
The core of their complaint is that if you use `jj edit` it's not obvious how to get a diff of what you did. The answer, of course, is that you can use `jj evolog -p`.
This is one thing that I constantly find myself wishing was in git but inevitably resign myself to knowing "thats just not how git works."
Some of it is also what a "branch" means to different people can mean different things: https://jvns.ca/blog/2023/11/23/branches-intuition-reality/
But yeah, as others have said, not really possible in a general way, sadly.
- the working copy has a bookmark pointing to it
- there's some ancestor with a bookmark
- there's a single linear path between the two with no other bookmarks in between
Here's an example that represents a branch containing 3 commits named "bookmark-05ff" branched off of "bookmark-6825".
> jj log -r y:: -T builtin_log_redacted
@ urplyywu user-482a 2025-10-23 13:24:52 bookmark-05ff a334e2e1
│ (empty) (redacted)
○ lxxtnlxw user-482a 2025-10-23 13:24:46 git_head() 7e32fa6b
│ (empty) (redacted)
○ omktyuos user-482a 2025-10-23 13:24:13 7668b0bb
│ (empty) (redacted)
○ ykzktoux user-7b7f 2025-10-23 13:23:47 bookmark-6825 98bfcbde
│ (empty) (redacted)
~
In this case, the following log would get you the commit pointed to by "bookmark-6825": > jj log -r 'latest(ancestors(@) & bookmarks(), 2) ~ @' -T builtin_log_redacted
○ ykzktoux user-7b7f 2025-10-23 13:23:47 bookmark-6825 98bfcbde
│ (empty) (redacted)
~
I'm using the builtin_log_redacted output template. Normally you'd have actual bookmark names, descriptions, user, etc.Also note this bakes in a lot of assumptions and is brittle. As many others have said, it’s not generalizable.
You might have a specific workflow such that you can actually answer your question, but it won’t generally apply to all repos.
Since a branch is really just a label for a specific commit, which may be at the end of a chain of successive parent commits, a branch isn’t really a first class structure, but a derived one.
You can get the fork point of a branch, which is a common ancestor commit shared by another branch, but that fork point is a commit and may not have a branch label. That commit can have any number of other branches going off of it: how would you decide which one is the parent vs just another sibling?
My assumption after looking at jj is that it is not as complicated as git yet. Give it time. It’s also not even as simple as git for many tasks, based on their own docs: https://jj-vcs.github.io/jj/latest/git-command-table/
You could probably attach metadata to commits indicating the branch name at time of creation, but there's probably a lot of weird edge cases to handle.
If you have another machine on main without any outstanding changes and you want to pull the latest changes that is probably also two steps (git fetch + new?)
That said, I've been liking jj quite a bit for more mature / collaborative projects. It has been a learning experience. (don't enjoy updating bookmarks for PR branches though; jj encourages rewriting history which is not my favorite choice for code review branches; I often work in repos that squash-on-merge).
For updating bookmarks I've found like half a dozen variants of `tug` alias the community has come to using which is just a slight improvement (bit daunting to newcomer to pick 'best' one and not fan setting up aliases on all my working devices).
It would be nice if jj was better than git for the fundamental workflows like this out of the box overall.
https://github.com/jj-vcs/jj/blob/c70f9b5b3fff08a86fb11afc57...