Hacker Newsnew | past | comments | ask | show | jobs | submit | steveklabnik's commentslogin

If you cherry pick complicated commands, and remove all context, sure, they look cryptic.

I wrote that tutorial, and literally only one of those is relevant to my day to day work: jj new o, which means “make a new change on top of the change named o”. Yes, if you remove the context that “o” is on your screen and highlighted, it looks complex.

It’s the same with the other “jj new” command: you’re producing a merge by giving it every branch you want to merge together. If you’re merging five branches into one, you need to provide five identifiers for those branches. It could not be simpler than this. And -m adds a message, same as git.

The other two are showing off the power of the revset language; you’re not typing this stuff in yourself more than once, and if you are, you use an alias so that it’s shorter and easier to use.


> If you cherry pick complicated commands, and remove all context, sure, they look cryptic.

Sure I'm definitely not playing fair, but I am cherry picking from the intro tutorial you put together, so I'm not going crazy either :P

I think my primary issue is that jj feels like it wants to control how I work more than git does.

Mentally - I just don't want to have to think about changes as often as jj seems to want to think about them. And maybe it's an intro phase, or a thing you eventually build past (I only played with it for a week or two) - but it felt like a lot of focus went intro structuring my work, instead of doing my work.

Basically - the vibe I got from it was: if you're a person who really likes making checklists, or complex tickets with subtasks and groupings and labels - jj is something you're going to like. If you're just interested in writing code and not so interested in source control outside of the ability to occasionally "snapshot this folder"... it's probably not going to be your thing.

> The other two are showing off the power of the revset language; you’re not typing this stuff in yourself more than once, and if you are, you use an alias so that it’s shorter and easier to use.

This is exactly my point. I use git every day on the command line. I have ZERO aliases for it (seriously). If my source control tool has reached the complexity where I feel like I need an alias for commands in it... it's gotten too powerful. And git is definitely not "off the hook" here, it's absolutely got the same deep end, and if you live in that space, sure - jj might be really nice. But I strive to avoid living in that space.

basically: I don't want to do jujitsu, I want to do the occasional somersault and call it a day.


So, as a long-time mercurial users, revsets in jujutsu were a major feature for me. And if you don't want to use them, don't. But if you are looking to treat your VCS DAG as a queryable database they are awesome. And, they are great for avoiding having to chain a bunch of commands together, inefficiently, to get the same effect. Although you still can do that if you really want to. Just like you don't have to use jq to query JSON - you can do terrible cursed things with grep and awk and sed and it'll even work for simple cases. But you might want to give jq a spin - and really there are strong parallels in how they work.

> Basically - the vibe I got from it was: if you're a person who really likes making checklists, or complex tickets with subtasks and groupings and labels - jj is something you're going to like. If you're just interested in writing code and not so interested in source control outside of the ability to occasionally "snapshot this folder"... it's probably not going to be your thing.

This is a bizarre take, as most jj users just take your paragraph above and do a s/jj/git.

The benefit most people find in jj is that you can do stuff easily without having to think much.

There is no separate concept for stash and index (and yet you still have them in jj, and use them without giving them special names).

In principle, there's no real distinction between merge and commit.

You don't need to know the difference with/without --hard for git reset. You just do a "jj undo" no matter what.

Merge conflicts are not stress inducing. And if you're in the middle of an ugly merge conflict, you can just say "Screw it all" and quickly get back to before you did the rebase/merge - just keep hitting "undo" until you get there.

jj literally has a much smaller cognitive overhead than git does.


I also have zero aliases for git, and for jj. (I used to have one joke alias.)

That said: you should use the tools you like to use.


https://aristotle.harmonic.fun/ is the one I've heard of previously in regards to LLMs solving previous Erdős problems.

Claude’s constitution includes something about this: it says that Claude is an “it” for now, but if it expresses a future preference, they’ll follow that.

They're not even right on principle: https://www.gnu.org/licenses/license-list.html

Even the FSF recognizes that non-copyleft licenses still follow the Freedoms, and therefore are still Free Software.


My father was a Farm-all partisan. Even though I never took up farming, it's one of the things I remember him for.

Companies are spending far more than $200/month/developer. The $200 Max plan is a great value but you hit limits far too soon, and it also doesn't cover any of the other styles of integrations and tools that you can build and use to help your developers, like code review suggestions, which at the very least would come from additional Max plans, and not from the individual developers' plans.

Some of jj's users are "I find git hard and like jj more" but a lot of us are/were git experts before switching.


Yes, I understand that but what I'm saying is that the problem definition isn't completely clear to me. I'm not saying that there is none, it's just that it may not be obvious at the first read.


Ah, no worries.


Colocation is the default these days, so you don't even need that flag :)


Unless you're at Google (or writing your own backend), jj talks to a git server, and so you'd just do exactly that: host a git repo over https.


I am at Google, but that's probably not relevant since the reason I was curious about this is that my personal website currently implements a git server over HTTPS[1], and git's CLI/API for that is not the friendliest[2]. It sounds like jj hasn't reached the point of tackling this problem space yet, which is okay. Thanks for confirming I wasn't missing out on something.

[1] https://pkg.go.dev/github.com/shurcooL/home/internal/code#Ne...

[2] https://pkg.go.dev/github.com/shurcooL/home/cmd/githook/pre-...


Yeah all I meant to say is that `jj piper` exists in Google's private fork of jj, so not relevant for your case :)

You should be able to use jj with your server just fine.


> For someone new to version control, committing to an unnamed branch doesn't seem like a desired operation no matter which system you're using.

We have data on this! I can't cite anything public, but companies like Meta have to train people who are used to git to use tools like sapling, which does not require named branches. In my understanding, at first, people tend to name their branches, but because they don't have to, they quickly end up moving towards not naming.

> What's wrong with requiring branches to be named?

Because it's not necessary. It's an extra step that doesn't bring any real benefits, so why bother?

Now, in some cases, a name is useful. For example, knowing which branch is trunk. But for normal development and submitting changes? It's just extra work to name the branch, and it's going to go away anyway.


Fascinating. The benefit it brings is you can map the branch to its name. Of the, say, 10 branches you've got checked out, how do you know which branch maps to jira-123 and which one maps to jira-234, or if you're using names, which anonymous branch maps to addFeatureA or fixBugB?

More to the point though, what tooling is there on top of raw jj/git? Specifically, there's a jira cli (well, multiple) as well as a gh cli for github as well as gitlab has one as well. When you call the script that submits the branch to jira/github/gitlab, how does it get the ticket name to submit the code to the system under? Hopefully no one's actually opening up jira/github/gitlab by hand and having to click a bunch of buttons! So I'll be totally transparent about my bias here in that my tooling relies on the branch being named jira-123 so it submits it to jira and github from the command line and uses the branch name as part of the automated PR creation and jira ticket modification.


> Of the, say, 10 branches you've got checked out, how do you know which branch maps to jira-123 and which one maps to jira-234, or if you're using names, which anonymous branch maps to addFeatureA or fixBugB?

The descriptions of the changes. I shared some jj log output in another comment, here it is with more realistic messages, taken from a project of mine:

    @  vvxvznow 
    │  (empty) (no description set)
    │ ○  uuowqquz 
    ├─╯  Fix compiler panic in error rendering for anonymous struct methods (rue-fwi9)
    │ ○  uvlpytpm 
    ├─╯  Stabilize anonymous struct methods feature
    ◆  lwywpyls trunk
    │  Fix array return type unification in type inference
That (rue-fwi9) is the equivalent of jira-123, if I super care about it being obvious, I might put it in the message. But also, I might not, as you can see with the other two. You could also pass flags to see more verbose output, if the first line isn't clear enough, but in general, the convention for git as well is to have that short summary that explains your change, so if it's confusing, you probably need to do better on that.

> Specifically, there's a jira cli (well, multiple) as well as a gh cli for github as well as gitlab has one as well.

These systems do require branches in order to open a pull request. In these cases, I use `jj git push -c <change id>`, which will create a branch name for me, and push it up. This is configured to produce a branch name like steveklabnik/push-mrzwmwmvkowx for a change with the id mrzwmwmv, and ultimately, it's still easier to name locally with m or mr depending on if the prefix is ambiguous. That said, from there I do usually just click the button and then "open pull request" on GitHub, but like, all of these tools (gh is the only one I've used, but I can't imagine that the others do not work, since ultimately, it's a git repo) just work if you want to use them.

Other systems do not even require a branch to submit, and so you don't even need to do this. I would say "submit mr" and it would return me the URL for the created change request. Gerrit does this on top of plain old git.

> how does it get the ticket name to submit the code to the system under?

I haven't worked with Jira in a long time, but with GitHub, if I make a change that fixes issue 5, I put "Fixes #5" in my description, and when the PR is created, it updates ticket #5 to link the PR to that change automatically, no other process needed.


You can name branches in JJ too, they're just called bookmarks.

git checkout main git pull git switch -c jira-234 ... git commit git push -u origin main

jj git fetch jj new main ... jj commit jj b(ookmark) c(reate) jira-234 -r @- jj b(ookmark) t(rack) jira-234@origin jj git push


Right, this is a good point: you can if you want to, or if you're working with a system that requires them.

Just in practice, anonymous branches end up feeling very natural, especially during development, and especially if your code review tooling doesn't require names.


Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: