News for hackers. Stuff that matters.
Re:jj: a Git-compatible VCS that is both simple and powerful by iFire on Tuesday February 11, 2025 @11:24PM (#43021866)
How does it compare against Facebook's Sapling? https://github.com/facebook/sapling
Re:jj: a Git-compatible VCS that is both simple and powerful by sophiebits on Wednesday February 12, 2025 @12:16AM (#43022131)
The first testimonial on this page is from Rain who has over 1,000 commits to the Sapling project and provides some context: https://jj-vcs.github.io/jj/latest/testimonials/#what-the-us...
Re:jj: a Git-compatible VCS that is both simple and powerful by sunshowers on Wednesday February 12, 2025 @12:31AM (#43022201)
(Hi Sophie!)

I still stand by my testimonial! My greatest achievement has been convincing Steve Klabnik to try out Jujutsu.

I also saw a comment from JJ's lead author martinvonz, where he pointed out that adding new functionality is much simpler to jj than it is to older systems like Git and Sapling/Mercurial. Having each spent many years working on source control, both Martin and I came to a general belief that a lot of implementation complexity comes from the modal states created by merge conflicts. Because Jujutsu's core UX is more straightforward, this is less of an issue and Jujutsu's devs can prototype changes quicker.

Re:jj: a Git-compatible VCS that is both simple and powerful by Timothee on Wednesday February 12, 2025 @01:06AM (#43022377)
> My greatest achievement has been convincing Steve Klabnik to try out Jujutsu

I came across jj from a recent Bluesky post by Steve Klabnik who was talking about having to learn something with git. That seemed very odd to me. I then gathered that he (and many others in the comments) had been using jj exclusively for some time.

I haven't had time to give it a try, but I definitely will. Your achievement has ripple effects.

Re:jj: a Git-compatible VCS that is both simple and powerful by rjzzleep on Tuesday February 11, 2025 @11:29PM (#43021901)
> Mercurial & Sapling: There are many Mercurial-inspired features, such as the revset language to select commits. There is no explicit index or staging area. Branches are "anonymous" like Mercurial, so you don't need to make up a name for each small change. Primitives for rewriting history are powerful and simple. Formatting output is done with a robust template language that can be configured by the user.

Can anyone explain why people want something like JJ? Is it simplicity? I actually quite like the staging and index in git. Although it took me a while to grok.

Looking at the other thread though I don't think it's more simple. It's just different. https://news.ycombinator.com/item?id=43020180

Re:jj: a Git-compatible VCS that is both simple and powerful by mpalmer on Tuesday February 11, 2025 @11:45PM (#43021983)
jj is nicer to learn first, but also, knowing both git and jj I do pick jj.

Significantly nicer UI, very simple but powerfully expressive DSLs for formatting logs and selecting revisions to log, respectively.

For me it clicked when I really grasped how the latter DSL (called the revset language) wasn't just for selectively logging, it was for selecting commits/changes to act upon. The revset grammar is about specifying subgraphs of the graph of changes. Using it, and taking advantage of jj's by-design automatic rebasing of downstream commits, you'll eventually think nothing of rebasing N branches in a single command.

Even conflicts are less trouble when they crop up during auto-rebasing. jj leaves conflicts on the change where they originated, and marks that commit (and all downstream ones) as conflicted. Fixing conflicts is no longer a "drop everything and fix" matter; you can decide when to fix them without delaying work on other parts of the tree.

Haven't even gotten into the optional auto committing on every file change (it's better than it sounds). You might miss the staging area for a bit, and then you realize that there isn't really a difference between the staging area and a "current commit" that stays up to date on its own.

I guess what I'm saying is I would recommend it.

Re:jj: a Git-compatible VCS that is both simple and powerful by kemayo on Tuesday February 11, 2025 @11:34PM (#43021931)
I'm sympathetic to the simplicity argument. I've recently had to help someone who's new to coding with some getting-started-with-git issues, and it's definitely reminding me of the appeal of a system that you can't screw up in various interesting manners and then need someone who understands its inner workings to fix.
Re:jj: a Git-compatible VCS that is both simple and powerful by MForster on Tuesday February 11, 2025 @11:35PM (#43021935)
You can still use a similar workflow as with the index. The difference is that the staging area is modeled as a commit, so it's not another concept that will take a while to grok.

Same with the working copy.

Re:jj: a Git-compatible VCS that is both simple and powerful by recursive on Wednesday February 12, 2025 @12:19AM (#43022148)
I've wished I could turn the staging area off in git since before jj was a thing. If you like how git works, then you probably prefer it to the alternatives. There are things I like about git, but some of its design choices are hard for me to understand.
Re:jj: a Git-compatible VCS that is both simple and powerful by sunshowers on Wednesday February 12, 2025 @12:25AM (#43022173)
Jujutsu has all of the power of the index without actually having the index as a separate construct -- index operations become commit operations. It is quite meaningfully simpler than Git as it can express the same degree of power (actually a lot more) through fewer concepts.
Re:jj: a Git-compatible VCS that is both simple and powerful by arxanas on Wednesday February 12, 2025 @01:24AM (#43022473)
I don't think the cheat sheet in that thread demonstrates any of jj's improved expressive power, such as revsets or first-class conflicts. I gave an example of something difficult do in Git here: https://news.ycombinator.com/item?id=43022367
Re:jj: a Git-compatible VCS that is both simple and powerful by rtpg on Wednesday February 12, 2025 @01:25AM (#43022475)
jj makes it super easy to "fix up" your commit tree to what you want it to look like.

"Oh I forgot to make a change in this commit and I'm 4 commits in..." -> "I can go change that commit and everything else magically rebases on it".

It treats changes as this conceptual thing, and the whole immutable commit thing as a backing store but not how _you_ are looking at a problem. Or at least not how I look at it.

I added a test, put in a new feature, updated the readme. Those changes are not about all the metadata around the change, they're the change. Of course you still have the immutable commit graph when you want to _really specifically_ talk about a certain commit, but for most intents and purposes it's the changes that matter.

jj gives you similar workflows to git in the easy case. In the hard cases, jj makes it easier to do the work than git. So it's nicer!

Re:jj: a Git-compatible VCS that is both simple and powerful by gpm on Wednesday February 12, 2025 @02:03AM (#43022644)
> jj makes it super easy to "fix up" your commit tree to what you want it to look like.

I hit this today in a fun way. I was working along as one does, and needed to write a parser for a simple s-expression based language. So I did that fairly quickly, added a few tests which appeared to pass, and kept on working.

A few commits later I reached a point where I needed to manually test my code. And promptly hit a stack overflow in the parser. A few minutes of debugging I understood the issue (I'd used the wrong function and failed to require brackets around a nested s-expression) - except I could have sworn my tests should catch it. So I ran my tests manually, and lo and behold they did catch it.

Turns out that there was a bug in the tool I was using to run my tests [1] that was masking the test failure. I had completely broken my tests for the last few commits (all of them since I wrote the parser).

Anyways, I went and fixed the tool, but by now on my main repo I had fixes for the last few commits all mixed together with a fairly large WIP commit. Thankfully instead of making this the frustrating game of rebasing with git, jj makes it just take a few jj split (select changes you want to split off, sort like git add -p); jj squash (merging changes into the existing commit) commands.

Could I have fixed up the previous commits with git? Of course. But it would have made a frustrating hour even more frustrating.

[1] https://github.com/Canop/bacon/issues/326

Re:jj: a Git-compatible VCS that is both simple and powerful by Izkata on Wednesday February 12, 2025 @10:13PM (#43032288)
If I'm understanding right, that would also be 2 commands in git and you even mentioned one of them: "git add -p" to create a new commit with the fix, separating it from the rest of the WIP, then "git rebase -i <old commit>" and use the file it opens to tell git which commits to combine. Save and quit, and git does the rest for you.

There's other functionality in there too, including just straight editing old commits without having to deal with the child commits yourself.

Re:jj: a Git-compatible VCS that is both simple and powerful by gpm on Wednesday February 12, 2025 @10:43PM (#43032453)
You're... not wrong. You're also missing the point, which is on me.

It's `git rebase -i`, and edit a file to tell it what to do, and work in a limited rebase-state of git. Versus `jj squash --into <commit>` and if doesn't merge nicely, or it causes conflicts, you stay in the normal state with the normal tools. It's a difference in quality of life, of reducing friction, not the power of the tools.

Even the `git add -p`s interface is also just less nice than `jj split`'s interface. Where `git add -p` feeds you changes one at a time and makes you select them, `jj split` gives you a interactive selection gui that lets you scroll through changes, collapse and uncollapse files, select and unselect whole files, single diff sections, or even indivudal lines. It's nicer.

> including just straight editing old commits without having to deal with the child commits yourself.

This is sort of an example. Git needs a special mode, invoked via this file-based interface in `rebase -i` (though I imagine there's a more direct command that no one knows as well). While in that mode you can't do things like just switch to another branch and work on something else. It's "strange".

In jj this is just `jj edit <commit>`. It's within the set of operations that are "normal" in jj's model. You can do everything you can normally do.

If something like a merge conflict happens git says "and how you need to deal with this right away". jj says "these commits have merge conflicts in them, fix them if/when you like".

Every small piece of my interaction feels slightly better than the same small piece of the interaction with git, and it's remarkable because it really does feel like it's every piece of the interaction with jj that is better.

I don't feel like I'm being very eloquent - but hopefully the difference I'm trying to describe is coming across at least to some degree.

Re:jj: a Git-compatible VCS that is both simple and powerful by MrJohz on Wednesday February 12, 2025 @01:35AM (#43022525)
I agree that you probably want to keep staging, but one of the advantages of JJ is that staging is just a change* like any other change in your history.

There are a couple of different ways that people use JJ, but I normally use the "squash" approach. When I want to make a new branch/pr/etc, I run `jj new master` (to create a new change off the master bench), and then I run `jj new` again. This gives me two empty changes - the older change is where I'm going to store my work when I'm finished, and the newer change is where I'm going to actually be working. This functions like staging. As I edit files, the staging change fills up. When I think I'm finished, I can run `jj diff` to exactly what's in my staging change. If I want to keep all of it, I can run `jj squash` to squash the entire change into the parent change, or I can run `jj squash -i` to interactively squash the bits that I want to keep, and keep the rest in staging.

You might argue that we've just reinvented the wheel - we used to have a pseudo-commit as our staging/index, and now we have a JJ change, but we're still doing the same thing with it. This is true, but the value of having our staging area be a change, i.e. a first class entity in our VCS, is that we don't need to special case it any more. Every command that works for our staging area works for any other change in our history. This is simpler because there's less stuff going on (fewer commands, fewer concepts), but we still have the same capabilities as before. On top of that, because our staging area is just another change, it is automatically stored in the local repository history. This means that if I've got stuff staged and I want to create a new branch somewhere else, I can do `jj new master`, and the stuff I've got staged will stay where it is. This also removes the need for an explicit stash: if all the work I'm doing is already part of a change, I don't need to create temporary "stash" commits to store them, they're already stored. Again, fewer commands, fewer concepts.

Just by itself, I find this feature really helpful because it simplifies how I need to think about changes a lot. It's so much easier to navigate around a repository like this. But it's just one of the features that has been simplified from existing VCSs. For example, you've also got automatic rebases - you can make a change to an older change (either directly or using something like `jj squash`), and all the parent change will automatically get rebased. Sometimes this causes conflicts, but it never fails. Instead, conflict tracking is part of the history itself. This allows you to fix conflicts in your own time - you're not put into the "rebase world" like in Git, where Git needs to statefully remember that it's currently doing a rebase, and you need to use different commands to resolve a rebase conflict than you need to commit a merge conflict, say. No, conflicts are first-class, which again massively simplifies how you interact with the repository - fewer commands, fewer concepts.

This is what I think people mean by simple - it's not simple in the sense of "make everything easy by wrapping it in an abstraction", instead it's simple in the sense of "find the ideal underlying model to expose to the user". Version control is always going to be fairly complex, but JJ feels like something that is very close to the minimum complexity required for a VCS: no simpler (because then it wouldn't work very well), but also but very much more complex.

* "Change" in this context refers to JJ's equivalent of commits, i.e. the individual rows you see when your run `jj log`.

Re:jj: a Git-compatible VCS that is both simple and powerful by mmmulani on Wednesday February 12, 2025 @12:03AM (#43022075)
I tried out both for a week each and much prefer Sapling.

jj always, automatically turns your current state (even if it's empty) into a "change" which is like a commit (it has a hash). in practice, this was actually incredibly annoying. when working in git, you often think about the current commit you're on, and amending/making a new commit. with jj, you're actually making "changes" (which are like commits) constantly. it's also so infuriating that there are two sets of hashes, jj changes and git commits, and they are not the same/interchangable.

on the flip side, sapling has been a breeze. it does force you to one commit per PR (which might be annoying to some but if you're going to squash the commit into main when you commit, why not do it locally too). its inter-op with github is really nice, you can do `sl goto pr1234` and it will just bring you to the code for pr #1234 (and fetch it in the process if you don't have it locally).

Re:jj: a Git-compatible VCS that is both simple and powerful by jjfanboy on Wednesday February 12, 2025 @12:23AM (#43022164)
> . when working in git, you often think about the current commit you're on, and amending/making a new commit. with jj, you're actually making "changes" (which are like commits) constantly

I don't know what this means, and it seems like a fairly large misunderstanding.

Re:jj: a Git-compatible VCS that is both simple and powerful by stouset on Wednesday February 12, 2025 @01:10AM (#43022400)
What did you find annoying or infuriating about this? It’s quite possibly jj’s most beloved feature. Since all of your changes are constantly being recorded, you're covered by your VCS even if you don’t commit.

As a 1+ year jj user now, I can’t think of a single time I’ve needed to use a git hash. They’re there underlying things, but you’re always just using revision IDs.

Re:jj: a Git-compatible VCS that is both simple and powerful by eitland on Wednesday February 12, 2025 @03:06AM (#43023021)
Haven't tried jj, but one thing that immediately strikes me is that for us who use IDEs, git hashes are all that we can see in that view.

I've been considering trying out jj and thought it could work since it uses git as store, but if I need to keep track of different hashes based on if I access version control from my IDE (primarily IntelliJ for now) or from my command line, that seems like an actual problem to me.

(I'm also used to work in the command line and I prefer it to point and click for many things, but version control is one of the things that I much prefer do approach from the same place I write my code.)

Re:jj: a Git-compatible VCS that is both simple and powerful by wocram on Wednesday February 12, 2025 @02:31AM (#43022821)
What do you get out of using sapling without mononoke or eden?
Re:jj: a Git-compatible VCS that is both simple and powerful by Shish2k on Wednesday February 12, 2025 @10:56AM (#43026605)
I've been using the Sapling CLI frontend with GitHub as a backend for all my open source projects for a few years now (I've also used mononoke and eden at work, but IMO those only apply to people with hundred-gigabyte monorepos). So speaking based on my open source work:

- I am absolutely loving the improved UI/UX for common operations - being able to do the same actions with fewer commands and fewer concepts to understand, and much more helpful error messages when I try to do something invalid

- The existence of some unique features (`split`, `absorb`, and `restack` being particular favourites -- IIRC people have created third-party scripts to replicate these commands for git, but last I checked they weren't as good, and they aren't installed by default)

- Having the commit log integrated with github (being able to see which of my branches match to which PRs, and whether the PR is unreviewed / accepted / rejected / merged)

Re:jj: a Git-compatible VCS that is both simple and powerful by MForster on Tuesday February 11, 2025 @11:29PM (#43021905)
Re:jj: a Git-compatible VCS that is both simple and powerful by Shish2k on Wednesday February 12, 2025 @10:40AM (#43026435)
> Sapling supports cloning, pushing, and pulling from a remote Git repo. jj also does, and it also supports sharing a working copy with a Git repo, so you can use jj and git interchangeably in the same repo

As a minor update - sapling now also supports the .git on-disk formats so that you can use git and sl interchangeably in the same repo