frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

Open in hackernews

What is jj and why should I care?

https://steveklabnik.github.io/jujutsu-tutorial/introduction/what-is-jj-and-why-should-i-care.html
289•tigerlily•4h ago

Comments

dgb23•3h ago
The last paragraph might be the most important one:

> There's one other reason you should be interested in giving jj a try: it has a git compatible backend, and so you can use jj on your own, without requiring anyone else you're working with to convert too. This means that there's no real downside to giving it a shot; if it's not for you, you're not giving up all of the history you wrote with it, and can go right back to git with no issues.

eru•2h ago
Funnily enough, that's how I used git with CVS and Subversion, too.
jeremyjh•2h ago
But this is not true. They are interoperable but far from seamless. Those features mainly support migration use cases or things like git deployment from an repo managed in jj. Operations git does are not in jj’s log. You have to constantly import them. The project recommends a single primary interface.
miyoji•1h ago
But it is true. I (and many others) happily use jj on teams that use git without anyone else on the team using jj or knowing (or caring) what I'm using.
maleldil•1h ago
If you constantly switch between the two, you're going to have a hard time, but you can take a git repo, try jj for a while, and if you decide to go back, you don't lose anything.
jeremyjh•1h ago
Right, but that’s different from working in a team environment where everyone else continues using git.
saghm•1h ago
How so? I've used `jj` locally on teams where most (if not all) of the other team members were using git, and they only found out I was using `jj` when I told them.
ongy•1h ago
I think you are talking about colocation, which is slightly different than the `jj git push` `jj git fetch` type commands.

Colocation has its uses bit is a bit finicky. The push/pull compatibility works perfectly fine (with some caveats of github being broken that can be worked around).

asdfasgasdgasdg•1h ago
Most importantly, submodules are not fully supported, which are used by almost every open source project at least in the space I work in (embedded). So you can't use jj to easily contribute back to those project. It can be done but you always have to be cognizant of whether a submodule has changed between two branches or when you sync, since they don't update automatically the way they do with git.
saghm•1h ago
It's been over a year since I last used git manually in the CLI, and I've exclusively worked with git remotes. The only time I had any friction was on a team where stale code-gen output was checked into the repo and for whatever reason no one was willing to either add it to the `.gitignore` or commit (pun intended) to keeping it up to date, meaning that I had to manually remove the changes from when I compiled before pushing. I would have argued in favor of adding to .gitignore or keeping it up to date even if I didn't use `jj` though because I think having stale output checked in is just silly.
IshKebab•1h ago
Big caveat: do not try to use Git and JJ in the same directory. It's probably fine if you only use JJ, but if you mix them you will horribly break things.
surajrmal•9m ago
This isn't true?
verdverm•1h ago
Unless you use LFS, submodules, or hooks at your org.
tucnak•3h ago
16 year-old me would have been very impressed by this!
auggierose•3h ago
Is that a compliment, or the opposite?
tucnak•3h ago
A bit of both. I guess it's nice, but nothing I actually care about.
xtracto•2h ago
I had a similar thought: there surely are lots of young folks who will be all excited with this (I was back in the CVS/SVN days when git appeared).

But nowadays I'm extremely lazy to attempt to learn this new thing. Git works, I kind of know it and I understand its flow.

nithril•2h ago
Same here, I’m not experiencing so much friction to justify looking for an alternative
cestith•1h ago
We still have some repos in Subversion and most things in git. It’s still exciting for every repo we get migrated out of svn. That’s a high bar to cross if we’re talking further improvements compared to git though.
steveklabnik•17m ago
I was 38 or 39 when I found jj.
jansan•3h ago
We all need to give ourselves a push and finally make the next step in version control. Github, Google, Microsoft, Meta (did I forget anyone relevant? Probably) should just join forces and finally make it happen, which should not be a problem with a new system that is backend compatible to Git. Sure, Github may lose some appeal to their brand name, but hey, this is actually for making the world a better place.
ramblerman•3h ago
The new solution is better. It’s so good we must get all the big players to mandate its usage.

If ur making an appeal on a forum like this u could have gone with ur favorite feature, or anything else really.

jansan•2h ago
It is not about starting over, like moving from CVS or Subversion to Git. jj is backend compatible to Git, so nothing really had to change on the backend.

It's just that although Git was created by Linus Torvalds it is not perfect and could be more beginner friendly. But efforts to improve this should be concerted, not individual efforts.

And it does not have to be jj. I just think there is room for improvement, and not to alienate old farts it could be called GitNext, GitStep, GitFlow or similar to emphasize that is still is just Git, only with an improved front end.

Maybe Linus Torvalds himself should start the initiative.

SOLAR_FIELDS•3h ago
Every time I see a statement like this I wonder what specific features of git that people feel like are terrible enough that it’s time to completely start over. Besides “the UX is kinda shit and it’s confusing to learn”, which there are many solutions for already that don’t involve reinventing a pretty good wheel.
seanhunter•3h ago
Right.

How we got git was cvs was totally terrible[1], so Linus refused to use it. Larry McEvoy persuaded Linus to use Bitkeeper for the Linux kernel development effort. After trying Bitkeeper for a while, Linus did the thing of writing v0 of git in a weekend in a response to what he saw as the shortcomings of Bitkeeper for his workflow.[2]

But the point is there had already been vcs that saw wide adoption, serious attempts to address shortcomings in those (perforce and bitkeeper in particular) and then git was created to address specific shortcomings in those systems.

It wasn't born out of just a general "I wish there was something easier than rebase" whine or a desire to create the next thing. I haven't seen anything that comes close to being compelling in that respect. jj comes into that bucket for me. It looks "fine". Like if I was forced to use it I wouldn't complain. It doesn't look materially better than git in any way whatsoever though, and articles like this which say "it has no index" make me respond with "Like ok whatever bro". It really makes no practical difference to me whether the VCS has an index.

[1] I speak as someone who maintained a CVS repo with nearly 700 active developers and >20mm lines of code. When someone made a mistake and you had to go in and edit the repo files in binary format it was genuinely terrifying.

[2] In a cave. From a box of scraps. You get the idea.

bombcar•2h ago
To be fair the "shortcomings" that spurred it on mainly were the Samba guys (or just one) reverse-engineering Bitkeeper causing the kernel free license getting pulled, which caused Linus to say "I can build my own with blackjack and pre-commit hooks" and then he did, addressing it toward his exact use case.

It gained tons of popularity mainly because of Linus being behind it; similar projects already existed when it was released.

xtracto•2h ago
Mercurial was there, was better and more complete.

Too sad it didnt win the VCS wars.

seanhunter•2h ago
When I tried both at that time hg was just really slow so I just adopted git for all my personal projects because it was fast and a lot better than cvs. I imagine others were the same.
bombcar•1h ago
I went with bzr mainly because it had an easy way to plugin "revision" into my documents in a way I could understand and monotonously increment.

hg was slow though I don't know how bzr compared as I was using it pretty light-weight.

mhh__•3h ago
Git is basically fine even though the verbs are backwards - e.g. you shouldn't need to name branches, commits should be far more automatic, but the basic mechanisms are fine.

GitHub is an abomination.

dieortin•1h ago
You might already be aware, but jj fixes exactly those complaints you have with git
bluGill•2h ago
Coming from mercurial (which is older than git), git doesn't understand a branch. Instead of a branch you get a tag that moves, which is very different. Too often I'm trying to figure out where something came in, and but there is just a series of commits with no information of which commits are related. Git then developed the squash+rebase workflow which softof gets around this, but it makes commit longer (bad), and loses the real history of what happened.

Git was not the first DVCS, there were better ones even when it was made. But Linus pushed git and people followed like sheep.

(I'm using git, both because everyone else is, and also because github exists - turns out nobody even wants a DVCS, they want a central version control system with the warts of SVN fixed).

jcranmer•1h ago
> Coming from mercurial (which is older than git)

Git is older than mercurial by 12 days. Bazaar has git beat by about the same amount of time. The major DVCSes all came out within a month of each other.

> But Linus pushed git and people followed like sheep.

I don't think this is true. Until around 2010-2011 or so, projects moving to DVCS seemed to pick up not git but mercurial. The main impetus I think was not Linux choosing git but the collapse of alternate code hosting places other than GitHub, which essentially forced git.

em-bee•1h ago
the lack of a proper branch history is also the main pain point for me. but i disagree that noone wants a DCVS. having a full copy of the history locally, and being able to clone from any repo to anywhere else and even merge repos (without merging branches) is a major win for me.
l72•1h ago
If git would change two defaults, that would make me really happy:

  1. git merge ONLY does merges (no fast forward/rebase). git pull ONLY does a fast forward
  2. git log by default is git log --first-parent. Just show commits where the parent is the current branch. This makes the merge workflow really easy to understand an linear, because in the end, you only care about commits on the trunk.
tom_alexander•3h ago
I'm giving jj a try but one aspect of it I dislike is edits to files are automatically committed, so you need to defensively create empty new commits for your changes. As in, want to browse the repo from a commit 2 weeks ago? Well if you just checkout that commit and then edit a file, you've automatically changed that commit in your repo and rebased everything after it on top of your new changes. So instead you create a new branch off of the old commit and add an empty commit to that branch so any file changes don't end up rewriting the past 2 weeks of history. git is much nicer in that I can do whatever I want to the files and it won't change the repo until _I tell it to_.
smackmybishop•3h ago
Just don't ever use `edit`, use `new` instead; then your changes are tracked without making a mess. I think that's much nicer than juggling stashes in git.
VMG•3h ago
... unless you actually want to edit a change!
throawayonthe•2h ago
well, you can do jj new <revision>, make your edit, and then do jj squash which will add the changes to the prev revision

i do this for example when i want to see a specific edit highlighted in my editor, it's a nice workflow i think

Aeolun•2h ago
This is exactly how someone explained Git to me 12 years ago or so, and I’ve finally wrapped my head around it. Not changing now.
hacker161•11m ago
It took you 12 years to grok git??
arccy•2h ago
still use new, and then squash your changes in. that way you can actually see what changes you made
incognito124•2h ago
then you `new` & `squash` :)
BeetleB•1h ago
I go back and forth between the two approaches, but because of the whole "accidentally made some temporary changes and now it's a pain to separate/undo them because not all changes were temporary", I also usually do a jj new and then jj squash.
embedding-shape•2h ago
> Just don't ever use `edit`, use `new` instead

As a git-ist (?), if I'd ever move away from git, it would be to avoid tooling that has idioms like this (like git too has), if `jj` just gonna surface a bunch of new "bad ideas" (together with what seems like really good ideas), kind of makes it feel like it isn't worth picking up unless you don't already know git.

surajrmal•1h ago
jj edit has good use cases, but it's not the default command you need. For instance, say you were working on some changes but had to change branches for a few minutes to do something. If you didn't manage to create a commit and want to go back to the previous staging area, you would use the jj edit command rather than jj new. It's very intuitive in my experience, something I can't say is true for managing git commits (unless you've spent years forcing it into muscle memory). I never need to run jj help. I run help commands with git all the time.
dzaima•1h ago
`edit` is still useful; just, for ..editing (!) something, instead of viewing it.

If you have some unfinished changes at the tip and want to temporarily checkout something 2 weeks ago, you `jj new` to there (similar to `git stash; git switch whatever`), and then later `jj edit your-old-tip` to go back (equivalent to `git switch main; git stash pop`; I think `jj edit` being an extended replacement for stash-popping things is a reasonable way to think about it). (and if you don't have any uncommitted changes, you always `jj new`)

jj also has a concept of immutable commits (defaulting to include tagged commits, and trunk at origin, which it'll disallow editing as a layer of defense)

saghm•1h ago
The idiom here is use `edit` if you want to edit a commit, and use `new` if you want to make a new commit. This works identically whether you specify the commit via branch name or commit id. I'm not sure why people are saying not to use `edit` ever. It's basically just a shorthand for staging and amending changes in an existing commit, and there's still a use case for that; it's just not "I want to see the changes on this old branch".
embedding-shape•52m ago
> Just don't ever use `edit`,

> The idiom here is use `edit` if you want to edit a commit

You know, you guys have fun with that, I'll continue using git which (probably) has the same amount of warts, but I already know them. I'll continue to refer new VCS users to jj, seems a lot easier to learn, but really don't have the interest to re-learn a bunch of ever-changing idioms.

saghm•9m ago
I disagree with the people saying "never use edit". There are plenty of people saying conflicting things about git too, and I'd argue that understanding edit versus new isn't anywhere close to the level of wart that having to get people to agree on merging versus rebasing. Like you said though, have fun with that!
joshuamorton•23m ago
I think it's because it's easy to make annoying mistakes (still easy to fix with undo) with edit. And it gains relatively little over new+squash. Edit is a useful power-feature, but I think for a novice, "never use it, only use the more well understood workflow of new+squash" is a good heuristic.
jdkoeck•2h ago
Wow, that’s a total deal breaker to me. Using git may require a complex mental model, but at least it’s not doing anything I didn’t ask for.
Diggsey•2h ago
You would have had to run `jj edit` in order for this to happen, so I think it's a stretch to say you didn't ask for the edit?

This is the main difference though: in git files can be `staged`, `unstaged` or `committed`, so at any one time there are 3 entire snapshots of the repo "active".

In `jj` there is only one kind of snapshot (a change) and only one is "active" (the current working directory). When you make changes to the working directory you are modifying that "change".

As others have mentioned, the equivalent to `git checkout` would be `jj new`, which ensures a new empty change exists above the one you are checking out, so that any changes you make go into that new change rather than affecting the existing one.

saghm•1h ago
Using `jj edit` will edit a commit you specify, and `jj new` will make a new empty commit after the one you specify. These work exactly the same whether you specify a commit by branch or by the hash. I'd argue that you're getting exactly what you ask for with these commands, and by comparison, what "checkout" is asking for is much less obvious (and depends on context). We've just internalized the bad behavior of git for so long that it's become normalized.
csmantle•2h ago
`jj new` works like `git checkout` most by creating an empty revision on the top. `jj edit` on the other hand resembles `git checkout; [edits...]; git add -A; git commit --amend --no-edit`.
arianvanp•2h ago
You can disable the auto staging of new files since recently which removed the main grype for me
smweber•2h ago
jj edit is the biggest jj footgun I can think of, as other comments said just use jj new. But also if you do accidentally edit or change something jj undo works surprisingly well.

I found when using jj it worked best for me when I stopped thinking in commits (which jj treats as very cheap “snapshots” of your code) and instead focus on the “changes”. Felt weird for me at first, but I realized when I was rebasing with git that’s how I viewed the logical changes I made anyway, jj just makes it explicit.

jj auto-rebasing doesn’t matter until you push changes, and once you do it marks them immutable, preventing you from accidentally rebasing changes that have been shared.

saghm•1h ago
> jj edit is the biggest jj footgun I can think of

Honestly, this is only because `git checkout` is so convoluted that we've collectively changed our expectations around the UX. "checkout" can mean switching to another branch (and creating it if you specify a flag but erroring if you don't), looking at a commit (in which case you have "detached HEAD" and can't actually make changes until you make a branch) or resetting a file to the current state of HEAD (and mercy on your soul if you happen to name a branch the same as one of your files). Instead of having potentially wildly different behavior based on the "type" of the thing you pass to it, `jj edit` only accepts one type: the commit you want to edit. A branch (or "bookmark", as jj seems to call it now) is another way of specifying the commit you want to edit, but it's still saying "edit the commit" and not "edit the bookmark". Unfortunately, the expectation for a lot of people seems to be that "edit" should have the same convoluted behavior as git, and I'm not sure how to bridge that gap without giving up part of what makes jj nice in the first place.

nightski•1h ago
It's not "wildly" different behavior based on the thing it's pointing to. In all 3 cases, the command is pointed at a commit and the behavior is the same. Once you know that branches/HEAD are just named pointers to commits, then it becomes obvious you are always just working on commits and branches/ids/HEAD etc are just ways of referencing them.
saghm•5m ago
> In all 3 cases, the command is pointed at a commit and the behavior is the same

    echo "something" >> foo.txt
    git checkout foo.txt
What's the name of the branch this is pointed at? If I have to run another git command to find out, then it's not "pointed" at it.
nomel•1h ago
> preventing you from accidentally rebasing changes that have been shared.

I think this ruins it for me then. I push my in-progress work, to my in-progress branches (then git-squash or whatever later, if needed). It makes switching between (lab) computers, dead or not, trivial.

Is there some "live remote" feature that could work for me, that just constantly force pushes to enabled branches?

saghm•1h ago
Nothing stops you from doing the equivalent of `git push --force` in `jj`. The flag is just named differently: `--ignore-immutable`. This is a global flag though, so it's available to all commands, and `jj` requires it whenever you're making changes to immutable commits, even locally. I'd argue that this is one of the killer features of `jj`, since by comparison `git rebase` treats everything the same whether you're squashing your own local commits on a feature branch or messing with the history of `main` in a way that would break things for everyone.
aseipp•26m ago
Yes, almost all JJ users do this constantly. Just "track" the particular branch. JJ has an idea that only some commits are immutable, the set of "immutable heads", and the default logic is something like "The main branch is always immutable, remote branches are immutable, 'tracked' remote branches are mutable." In other words, tracking a remote branch removes it from the set of immutable heads.

So just run:

    jj bookmark track myname/somecoolfeature --remote origin
and the default settings will Do What You Want. This is intended as a kind of safeguard so that you do not accidentally update someone else's work.

Some people configure the set of immutable heads to be the empty set so they can go wild.

Jenk•2h ago
This is literally jj's schtick and reason for existing, so I wouldn't be surprised if you decide it is not the tool for you.
tom_alexander•1h ago
Yeah, that's a very real possibility. On the bright side, jj is git-compatible so at least the two camps can live together in harmony.
saghm•1h ago
How are you "checking out" the old commit? It sounds like you're using `jj edit`, which I'd argue does what it says on the tin. Switch to using `jj new <branch>` and your problem goes away.
tom_alexander•57m ago
That avoids the problem for the specific workflow of checking out an old revision (and it was what I was describing with checking out a new branch off the old commit and adding a blank commit to that branch), but another way this design bites me: At work I am constantly jumping around numerous repos because I might be working on repo <foo> but then someone on my team will ask for help with repo <bar>. So I'll turn on screen sharing, open up repo <bar> and I'll type out psuedo-code into <bar> as I'm explaining things to them.

So if the last thing I did on <bar> was finish some work by making a new commit, then writing some changes, and then giving it a commit message with `jj desc`, then I am now polluting that commit with the unrelated explanatory psuedo-code. So when switching to a repo I'm not actively working in, I need to defensively remember to check the current `jj status` before typing in any files to make sure I am on an empty commit. With git, I can jump around repos and make explanatory edits willy-nilly, confident that my changes are distinct from real meaningful commits.

I guess one way to describe it is: we want to make it easy to make good commits and hard to make bad commits. jj seems to be prioritizing the former to the detriment of the latter. My personality prioritizes rigorous safety / lack of surprises.

icorbrey•39m ago
Fwiw I generally solve this by using `jj commit` instead of `jj desc` unless I'm specifically targeting something that isn't my working copy. Technically it violates the "we want commands to be orthogonal" guideline we use to write Jujutsu (otherwise this would indeed be `jj desc; jj new`) but as a habit it's never let me down
tom_alexander•18m ago
Ah, thanks! That's a command I haven't learned yet, so I'll have to check it out. I learned jj from the tutorial that was posted and I don't think it covered `jj commit` at all.
steveklabnik•8m ago
I didn't cover it for various reasons, but I think it's good to teach now that I've had more time to consider this sort of thing, so the next iteration will likely start by beginning with jj commit.
ersatz-matty•37m ago
From your "polluted" snapshot, you can run `jj commit -i` and use the TUI to select only what you want.
hacker161•6m ago
Just like you can run `git add -p`
et1337•36m ago
Jujutsu has a concept of mutable vs immutable commits to solve this. Usually everything in a remote branch is immutable. To work on a branch, I track it and that makes it mutable.
alunchbox•26m ago
if you loose an edit jj op log is incredible, I've saved a ton of work more-so now with AI's making mistakes. Also workspaces are super fast compared to git worktree's - same concept, different implementation.

I agree, that was a bit of an interesting approach but more-so than not it's been better in DX even though you have to 'unlearn' long term it's been a benefit IMO, but a soft one, not something you can measure easily.

baq•8m ago
> edits to files are automatically committed

this is a core feature and it makes jj possible - you're supposed to get used to jj new and jj squash into the previous bookmarked commit, which you map to the git branch head/PR.

IOW you're supposed to work on a detached git head and jj makes this easy and pleasant.

7e•3h ago
Is it better for AIs? That’s the only reason I would care.
VMG•3h ago
I've had mixed results.

Most models don't have a 100% correct CLI usage and either hallucinate or use some deprecated patterns.

However `jj undo` and the jj architecture generally make it difficult for agents to screw something up in a way that cannot be recovered.

glasner•2h ago
I've gone all in on jj with a OSS framework I'm building. With just a little extra context, the agents have been amazingly adapt at slicing and dicing with jj. Gives them a place to play without stomping on normal git processes.
joshka•2h ago
The cli and a few concepts have evolved with time past the model's knowledge cutoff dates, so you have to steer things a bit with skills and telling it to use --help a bit more regularly.

I find it reasonably good with lots of tweaking over time. (With any agent - ask it to do a retrospective on the tool use and find ways to avoid pain points when you hit problems and add that to your skill/local agents.md).

I expect git has a lot more historical information about how to fix random problems with source control errors. JJ is better at the actual tasks, but the models don't have as much in their training data.

rob74•2h ago
Still not finished unfortunately :( Guess Steve is currently busy writing the next big thing in programming languages (https://steveklabnik.com/writing/thirteen-years-of-rust-and-...) ?
surajrmal•1h ago
It hasn't been touched in 3 months: https://github.com/rue-language/rue .
BeetleB•1h ago
To be honest, while Steve's tutorial was what got me interested in jj, other tutorials were better in actually helping me understand it.
steveklabnik•19m ago
Nope, I have had zero time for personal projects lately, Rue is on the backburner until I do.

I've been busy at https://ersc.io/ (and spending time with my family, and playing Marathon...)

shuyang•2h ago
Has anyone found a good code review workflow with `jj`? My problem is that GitHub doesn't remember the content of the last reviewed SHA, so every time I push a new change from jj, reviewers lose the delta from their last reviewed commit.

To work around this I stopped moving revs (squash/rebase) after review starts, which creates awkward local graphs if I have to merge from main for merge conflicts. Graphite works but it's $$$, and phabricator/reviewable/gerritt all have significant onboarding hurdles.

roblabla•2h ago
I wonder if the recent github stack system could help with that (https://github.github.com/gh-stack/guides/ui/)
shuyang•2h ago
waitlist only :/ waiting to get in so i can test it out!
bananapub•2h ago
github added support for this in the last six hours - https://github.github.com/gh-stack/faq/#will-this-work-with-...
joshka•2h ago
The last reviewed sha is generally available on the PR page (not the changes page) when you force push. There should be a changes since review link somewhere near the push.

When reviewing, you can also mark individual files as reviewed (useful in larger reviews where you're incrementally reviewing files). If you do this, only files that are changed will be expanded when you come back to the review.

shuyang•2h ago
yeah, this is where my complaint is - github shows a "compare" button when I force push, but it's not linked to the PR review. The "file changed" status is often not granular enough - if I change one line, force push, the entire file gets marked as unreviewed. the github "changes since your last review" is commit-based, not sha-based.

what I want is something like graphite/gerritt/google's critique where after each force push, the review page shows only the true delta between the two shas (similar to the "compare" button in github, bu as a reviewable unit).

poked around on github, doesn't look like the stacked PR feature has affected this "changes since your last review" selector yet :(

nerdypepper•1h ago
https://tangled.org does exactly what you want :)

have a longer write up here: https://blog.tangled.org/stacking but we have "interdiffs", to view a delta from previous review. pull-requests advance in the form of immutable rounds much like the patch workflow on email.

we have been interdiffing and stacking for a while on to dogfood, sample PR: https://tangled.org/tangled.org/core/pulls/1265/round/1?diff...

saghm•53m ago
I haven't noticed any significant change in my workflow needed to accommodate this, but it might be because I've always used rebase rather than merge. `jj rebase -d main` will put my current branch on top of the main branch, and fixing conflicts in `jj` is a breath of fresh air compared to git.
swoorup•2h ago
I love jj, but mostly I use jjui.

I would like more uniformity in the way jjui handles commands when you are viewing changes vs when you are viewing files within a single change.

Often I just make my changes and leave it there without `new`, as I am not sure which file should go in a single commit. I just leave it there and I interactively commit later.

For me to use `new` more, I would like the ability to also simply be able to get a tree view of all changes, which contains file which contains file changes, so I could can have marks that span multiple changes and then either `split` or `commit` or `squash` the change, idk if there is a good word for it. Right now I can only mark within a single change, and I lose it once I navigate up.

joshka•2h ago
I use jj fairly regularly and I'm trying to understand what your approach means, but having difficulty following what you want to acheive here. Seems like you're using ambiguous language that isn't aligned - wdym by marks?
gcr•2h ago
In jjui, you can select multiple changes to squash/rebase by pressing space bar before pressing S or r. Is that what you mean?
swoorup•1h ago
yes exactly, pressing space bars to select them. I referred these selection as marks.
PUSH_AX•2h ago
If it ain't broke...
surajrmal•1h ago
I think there are a lot of things that work well but still get improved versions. For example, grep works well but there are plenty of better versions these days.
BeetleB•1h ago
As a Mercurial user, git was broken from day 1 :-)
butlike•2h ago
FWIW, it's a pretty decent fried fish chain in Chicago as well.
cestith•1h ago
And chicken. And they have a few other things like Italian beef.

They’re branching out, too. We had one in our neighborhood in Houston before moving back here to Illinois.

dhruv3006•2h ago
this looks pretty interesting.
enbugger•2h ago
1) Are there any benefits in replacing a personal private project git repo with jj? I usually just commit straight to master in order to just not to lose the changes and be able to roll back. 2) Are there any pros in doing so in a project with many large binary files (3d models, images)?
Jenk•2h ago
You don't replace. jj is backed by git anyway.
gcr•2h ago
You can switch an existing git repo to jj by using:

jj git init --git-repo my-repo

I think (but CANNOT PROMISE) that just removing the .jj folder will bring you back, but definitely take a backup of .git before you try this in case I’m wrong.

Jenk•2h ago
No that is correct when in colocate mode (which is the default mode). Simply removing the .jj folder will "de-jj" the repo entirely, but will leave you in a headless state. Simple to fix with a `git switch` though.

If you are _not_ in colocate mode, the .git folder is located _inside_ the .jj folder. So worth checking!

andrepd•2h ago
Is there a concise introduction / overview of jj? I've read 8 pages of this link and the author is still in preambles and considerations... Not my favourite style of article!
marcuskaz•2h ago
I wrote a brief intro to Jujutsu here: https://mkaz.blog/code/jujutsu-vcs
tiborsaas•2h ago
Does JJ really prefer for me to think backwards? It wants me to start with the new and describe command, but with git I first make the changes and name the changeset at the end of the workflow.

I also often end up with in a dirty repo state with multiple changes belonging to separate features or abstractions. I usually just pick the changes I want to group into a commit and clean up the state.

Since it's git compatible, it feels like it must work to add files and keep files uncommitted, but just by reading this tutorial I'm unsure.

Jenk•2h ago
It doesn't need you to think that way at all.

`jj new` simply means "create a new commit [ontop of <location>]" - you don't have to describe it immediately. I never do.

I know that the intention was to do that, and I tried forcing the habit, but I too found it counter-productive to invariably end up re-writing the description.

surajrmal•1h ago
I don't usually do that right away, but I often use squash or absorb to move additional changes into a commit I already made in my stack. I think the spirit still applies if you take that course.
smweber•2h ago
My preferred workflow is to start with a new change, pick the changes I want, then use jj commit to describe the change and create a new empty one on top. Feels very similar to my old git workflow.

If I end up with multiple features or abstractions in one change (equivalent to the “dirty repo”), jj split works very well as an alternative to the git add/git commit/repeat workflow tidying up one’s working copy.

pythonaut_16•2h ago
I also like `jj commit [paths]` to commit just a subset of files when I don't need hunk based splitting.

Like `jj commit -m 'Feature A' file1 file2` then `jj commit -m 'Feature B' file3 file 4`

surajrmal•1h ago
I use jj commit -i a lot when writing the paths is too tedious. What's nice is you can pass -i into most commands (squash, split, absorb, etc).
joshka•2h ago
> Does JJ really prefer for me to think backwards? It wants me to start with the new and describe command, but with git I first make the changes and name the changeset at the end of the workflow.

A good way to think of it is that jj new is an empty git staging area. There's still a `jj commit` command that allows you to desc then jj new.

> I also often end up with in a dirty repo state with multiple changes belonging to separate features or abstractions. I usually just pick the changes I want to group into a commit and clean up the state.

jj split allows you do to this pretty well.

> Since it's git compatible, it feels like it must work to add files and keep files uncommitted, but just by reading this tutorial I'm unsure.

In jj you always have a commit - it's just sometimes empty, sometimes full, has a stable changeid regardless. jj treats the commit as a calculated value based on the contents of your folder etc, rather than the unit of change.

saghm•1h ago
I often will use `jj new -B@` (which I made an alias for) followed by `jj squash -i` to split changes. I had no idea about `jj split`, so I need look into that!
miyoji•1h ago
> Does JJ really prefer for me to think backwards? It wants me to start with the new and describe command, but with git I first make the changes and name the changeset at the end of the workflow.

Yes, but this is not backwards, the way you do it in git is backwards. =)

SiempreViernes•58m ago
git promises "version control", this clearly implies that the versions predate the control: in this picture the git workflow is not backwards.
saghm•1h ago
Nothing stops you from making changes in a commit that has no description and then at the end doing `jj commit -m` to describe them and make a new commit in one go, which is essentially the same as git. The difference is that it's essentially amending in place as you make changes rather than needing to stage first.
fmckdkxkc•1h ago
Personally haven’t used jj but as far as dvcs’s are concerned Fossil is great complement to Git because it does things differently than git and truly has a decentralized feel.

The autosync feature is really nice too, and you can store backup repos in cloud storage folders and auto sync to those as well.

jezzamon•1h ago
That totally works and it's how I use jj. jj commit -i does what you would want
EliasWatson•1h ago
jj is very flexible when it comes to workflow. One thing to note is that commits don't have to have messages. What I tend to do is to run `jj new` frequently while I work on something and leave all of them without messages. Then when I'm ready to make my actual commit, I squash the temporary commits together and then add a message. If my changes are separable, I can split the commits before squashing. This workflow acts as a kind of undo history. I can easily go back to what I had 5 minutes ago and try a different approach, but then also jump back to my original changes if I want. It makes experimentation much easier compared to git.
minraws•1h ago
think of jj like,

I want to build xyz,

```

jj desc -m "feat: x y & z"

```

do the work.

```

jj split

```

Split up the parts and files that you want to be separate and name them.

This will also allow you to rename stuff.

```

jj bookmark create worklabel-1 -r rev1

jj bookmark create worklabel-2 -r rev2

# Push both commits

# since we just split them they are likely not inter-dependent

# so you can rebase them both to base

# assuming rev1 is already on top of base

jj rebase -s rev2 -d base

jj git push

```

That is it.

motbus3•1h ago
I am dumb. why is that better than a git branch or a git worktree ?
cornstalks•35m ago
If you're already super comfortable in git, it's not. I'm saying this as someone who recently converted from git to jj and never wants to go back.

You also don't have to follow what the GP said. I never say `jj describe` before writing code. I write the code then just say `jj commit -m "Foo stuff"`, just like I would in git.

The bigger difference I've noticed is:

1. Switching between changesets just feels more natural than git ever did. If I just run `jj` it shows me my tree of commits (think of it like showing you git's branches + their commits), and if I want to edit the code in one of them I just say `jj edit xyz`, or if I want to create a new commit on top of another one and branch it off in a new direction, I just say `jj new xyz`. It took a little bit for my brain to "get" jj and how it works because I was so used to git's branches, but I'm really enjoying the mental model.

2. `jj undo`. This alone is enough to convert me. I screwed something up when trying to sync something and had a bunch of conflicts I really didn't want to resolve and I knew could have been avoided if I did things differently, but my screwup was several operations ago! So I ran `jj undo`. And ran it again. And again. And again. And then I was back to my clean state several stages ago before I screwed up, despite having made several changes and operations since then. With git? Yeah I could have gotten it fixed and gone back. But every time I've had to do something like that in git, I'm only 25% confident I'm doing it right and I'm not screwing things up further.

3. Rebasing. When I would try to sync git to an upstream GitHub repo that used rebasing for PRs, I would always get merge conflicts. This was because I stack my changes on top of each other, but only merge in one at a time. Resyncing means my PR got a new commit hash, even though none of the code changed, and now git couldn't figure out how to merge this new unknown commit with my tree, even though it was the same commit I had locally, just a different hash. With jj? I never get merge conflicts anymore from that.

Overall the developer experience is just more enjoyable for me. I can't say jj's flow is fundamentally and objectively better than git's flow with branches, but personally and subjectively, I like it better.

baq•39m ago
it's actually git that makes you think backwards - in jj the working tree is a commit, in git it isn't until you at least stage it.

the working tree being a commit has wide ranging implications as all the commands that work with commits start working with the working tree by default.

shermantanktop•21m ago
This is me! I often find that in the process of making one change, I have also made several other changes, and only recognize that they are distinct after following the ideas to their natural conclusion.

Hence I have multiple workspaces, and I shelve changes a lot (IntelliJ. I end up with dirty repos too and that can be painful to cherry-pick from. Sometimes I just create a git patch so I can squirrel the diffs into a tmp file while I cleanup the commit candidate. I often let changes sit for several days while I work on something else so that I can come back and decide if it’s actually right.

It’s chaotic and I hide all this from coworkers in a bid to seem just a bit more professional.

I admire people who are very deliberate and plan ahead. But I need to get the code under my fingers before I have conviction about it.

palata•2h ago
I tried jj for a few months. It was fun to learn a new thing, but I haven't had a single case of "wow, this would have been a pain with git". Then I went back to git (it's been 6 months now) and I haven't had a single case of "this is so painful, I wish something better existed".

So it felt like the XKCD on "standards": I now have one versioning system, if I learn jj I will have two. What for?

Don't get me wrong: it's nice that jj exists and some people seem to love it. But I don't see a need for myself. Just like people seem to love Meson, but the consequence for me is that instead of dealing with CMake and Autotools, I now have to deal with CMake, Autotools and Meson.

EDIT: no need to downvote me: I tried jj and it is nice. I am just saying that from my point of view, it is not worth switching for me. I am not saying that you should not switch, though you probably should not try to force me to switch, that's all.

naasking•1h ago
> Then I went back to git (it's been 6 months now) and I haven't had a single case of "this is so painful, I wish something better existed".

The core issues are: how long did it take you to get there, how many lucky decisions did you have to make to not run into git footguns, and how many other people accidentally made different choices and so have very different experiences from you?

palata•37m ago
What you're saying is that other people may find jj easier for them, right?

I am fine with that. I am just saying that the "you should use jj, you will finally stop shooting yourself in the foot regularly" doesn't work so well for me, because I don't remember shooting myself in the foot with git.

BeetleB•1h ago
For me, it was kind of the same. I used jj. Really liked it, but did not find it all that much better than git.

Then, for various reasons, I switched back to git.

By day 2, I was missing jj.

Stuff like "jj undo" really is nice.

demorro•2h ago
This doesn't seem different enough to be worth the transitional cost, even if you don't need to actually move away from a git backend.
maleldil•1h ago
It is definitely worth a try. Just being able to squash changes to earlier commits without having to fiddle with fixups and interactive rebases is worth it for me. jj absorb is great too.
scotty79•1h ago
Does jj have partial clones of remote repo?
systems•1h ago
its almost impossible for me to tell if this better or worst than git i read few things about jj, and my conclusion

   1. its different
   2. very few user would really care about this difference 
i think git is good (not good enough, good just good, or really good) and unlike shells, i cant think of a reason to have mass migration to it

people use zsh because apple choose it, and pwsh because microsoft settled on it, on linux i am sure we can do better than bash, but it good enough and nothing justified replacing it (that being said, all 3 OSes should have settled non nushell)

in summary, if we couldnt replace bash on linux, i dont think anyone can replace git, git as an scm tool if far better than bash as a shell

porksoda•1h ago
I may be reading too deeply but it sounds like you haven't even tried it. You should! Its really hard to live without it, once you feel it in your fingers.
kccqzy•57m ago
> very few user would really care about this difference

Oh the user absolutely does if that user creates lots of branches and the branches are stacked on top of each other.

I get your feeling though; sometimes in my own private repositories I don’t bother creating branches at all. Then in this case jj doesn’t really make much of a difference.

qezz•1h ago
For those, who want to/need to keep some files uncommitted, the workaround I found is to put gitignore into some nested directory:

  mkdir junk
  echo '*' > junk/.gitignore
jj won't track those files under ./junk/

Also might be relevant for claude, since it wants to put its settings into the repo itself as `.claude/`:

  mkdir junk/.claude
  bwrap ... --bind "$(pwd)/junk/.claude" "$(pwd)/.claude" ...
For some more common files, I use global gitignore file as

  # ~/.gitconfig
  [core]
    excludesFile = ~/gitconf/gitignore_global

  # ~/gitconf/gitignore_global
  .envrc
  .direnv/*
tcoff91•46m ago
I run jj in colocated mode so I put stuff in .git/info/exclude if I want it ignored but not part of the main .gitignore
nailer•1h ago
JJ might be good (this article couldn't convey why in the "What is jj and why should I care?" page) but it's not 10x better than git, so it will likely die. Sorry, nothing personal, Mercurial/hg was a little bit better than git and died too. Network effects.

What has a change is ast-based version control.

You adding a feature to a function that uses a struct I renamed shouldn't be a conflict. Those actions don't confliuct with each other, unless you treat code as text - rather than a representation of the logic.

Ending merge conflicts might make a new version control 10x better than git, and therefore actually replace it.

saghm•50m ago
> JJ might be good (this article couldn't convey why in the "What is jj and why should I care?" page) but it's not 10x better than git, so it will likely die. Sorry, nothing personal, Mercurial/hg was a little bit better than git and died too. Network effects.

The difference is that I can (and do) use `jj` with existing git repos today without needing anyone else using the repo to change what they're doing. There's no need to replace something when it can exist alongside it indefinitely.

cageface•12m ago
Unless you need to work with a repo that uses submodules or lfs.
Nuzzerino•32m ago
Did you confirm that the network effects are applicable here before posting that?
aftbit•1h ago
Nope, git is good enough, and is the global standard. We don't need more new VCS.
cryptos•1h ago
Might be true, but Subversion was also good enough and a de-facto standard.
porksoda•1h ago
Great opinion. Have you tried it? It takes just 30 minutes to wash all the Stockholm syndrome off of you.
justinmayer•1h ago
Many folks aren’t aware that there is also an open-source, cross-platform desktop GUI application for Jujutsu called GG: https://github.com/gulbanana/gg

I mention it because while the jj command line interface is excellent, there are certain tasks that I find easier to perform with a graphical user interface. For example, I often want to quickly tap on various revisions and see their diffs. GG makes that kind of repository browsing — and certain squash operations — much more efficient for me.

If you’re interested in more information about GG, my co-host and I talked about it in a recent episode of the Abstractions podcast at about the 8:17 mark: https://shows.arrowloop.com/@abstractions/episodes/052-they-...

tcoff91•48m ago
jjui TUI is incredible also
ferfumarma•1h ago
Can jj iterate through a list of repositories and clone them all to local storage?

It isn't very hard to make a bash script to do it, but I have about six github repos, all of which frequently need to be put on a new machine. that kind of functionality would be cool to have out of the box.

hosteur•1h ago

    for url in url1 url2 ..; do git clone $url; done
That’s not really a script but a basic one liner.
Filligree•51m ago
No, but to be honest, why would you want it to? That's... well, you already showed the trivial one-liner.
saghm•58m ago
Are you accessing these boxes via ssh or using them directly? If it's via ssh, I'd expect that you would already be using the clipboard for copying the names of them rather than typing them out manually, at which point copying `git clone <a> && git clone <b> && ...` would achieve the same thing.
zingar•1h ago
"It's more powerful and easier" is a great claim, but I need examples in this opening page to convince me of the pain I could save myself or the awesome things I'm living without.
baq•41m ago
does trivially working on 3 PRs in a single checkout and pushing focused changes to each one independently without thinking twice count?

if you don't need this, you might not see any value in jj and that's ok. you might use magit to get the same workflow (maybe? haven't used magit personally) and that's also ok.

alphabetag675•35m ago
Actually it is a anti-demo, because while software allows you to do it, I don't think many software engineers can work on this.
VanTodi•33m ago
Guess he was talking about the presentation, not what the tool can achieve. It has no hard proof on the first page, which could easily just be a LinkedIn pitch, but not on hackernews
tinco•31m ago
It might count, but it is easy with git as well, what is the feature in jj that makes this easier? Switching branches and pushing changes to remotes is the core feature of git and in my opinion really easy so I'm curious how jj improves on it.
baq•11m ago
rebases don't lose branches and jj absorb trivially squashes changes to the correct head (or leaves changes alone if it can't find where to squash).

is it possible in git? yeah, I've done it; there's a reason I haven't done it more than a few times with git, though. ergonomics matter.

VonGallifrey•18m ago
Can you show how you would do this in jj?

I know how I would do this in git, but don't really see how this would be in jj. I currently don't use it in my workflow, but if it is super easy in jj then I could see myself switching.

baq•13m ago
the beauty of it is there's not much to show; I use a crude jjui approach where I have an octopus merge working tree commit (in command line terms, jj new PR_A PR_B PR_C) and either use native jj absorb (S-A in jjui) which guesses where to squash based on the path or, when I'm feeling fancy, rebase the octopus via jjui set parents (S-M) function (also handy to clean up parents when one of the PRs gets merged).
steveklabnik•25m ago
This is good feedback, for sure, thank you. It's sometimes hard to come up with truly concise examples, but that's also why they're so valuable.
ersatz-matty•23m ago
Consider using the table of contents on the left of the page to view "Real World Workflows", "Branching, Merging, and Conflicts", and then "Sharing Your Code with Others" and then evaluate how JJ does things against your current git workflow. This requires some minor effort on your part.

The official JJ docs also have a "bird's eye view" introduction and tutorial available here: https://docs.jj-vcs.dev/latest/tutorial/.

latortuga•22m ago
Yeah we moved on from SVN to git because SVN branches were truly a pain in the ass to work with. I truly do not have any rough edges or big pains in my day to day git workflow.
qznc•21m ago
There is no index anymore. I guess that is the "easier" part.
steveklabnik•11m ago
That is, but not directly.

The general idea here is that jj has fewer and more orthogonal concepts than git. This makes it more regular, which is what I mean by "easy."

So for example, there is no index as a separate concept. But if you like to stage changes, you can accomplish this through a workflow, rather than a separate feature. This makes various things less complex: the equivalent of git reset doesn't need --hard, --soft, --mixed, because the index isn't a separate concept: it's just a commit. This also makes it more powerful: you can use any command that works on commits on your index.

This is repeated across jj's design in general.

surajrmal•17m ago
Specific commands don't really showcase the appeal of jj. If anything they might scare someone at first glance. It's the fact that the workflows are intuitive and you never find yourself reaching for help to get something done. You really need to try it to understand it.
tomnipotent•5m ago
> that the workflows are intuitive

It can't be both intuitive and yet too complicated to show examples at the same time.

zhaoyongjie•1h ago
To be honest, JJ is dick in Chinese, literally.
verdverm•1h ago
https://chinese.stackexchange.com/questions/31646/is-jj-slan...
mi_lk•1h ago
Please update the "Stacked PRs" workflow article Steve...
steveklabnik•20m ago
I'll get there... someday...
ux266478•1h ago
Clicked on this hoping it would be the irc client, very disappointed!

For those in the know, how does jujutsu stack up to something like Darcs?

steveklabnik•17m ago
jj is still snapshot based.
BeetleB•1h ago
One of my favorite jj features is "jj absorb".

For each change you've made in the current revision, it finds the last commit where you made a change near there, and moves your changes to that commit.

Really handy when you forgot to make a change to some config file or .gitignore. You just "jj new", make the changes, and "jj absorb". No need to make a new commit or figure out where to rebase to.

xixixao•1h ago
git absorb exists too fyi
SV_BubbleTime•1h ago
>You can request to not use the pager by using jj st --no-pager, or if you hate the pager and want to turn it off, you can configure that with

    $ jj config set --user ui.paginate never
In one feature they can’t help themselves from calling it two different things already.

Why do this? Why can’t the very clearly smart people making things step 1/2 step outside themselves and think about it like they are the users they want?

Earlier they talk about the native format and how it isn’t ready… so that to start you need

    jj git init
… but… if they’re planning a native format that makes no sense as a command. It would be ‘jj native init’ later?

Early planning keys/plans imo but those rarely change so as to not accept your early adopters.

These seem like small things but to me it’s a warning.

Philpax•23m ago
1. Pagination with a pager is a reasonable default. See `git log`.

2. The native format would be `jj init`. For precedent, see how uv dealt with its pip compatibility: `uv pip install` was obsoleted by `uv add`.

QuiDortDine•1h ago
> $ cargo install jj-cli@0.23.0 --locked

I won't install Rust just to test your software. Make a debian package like everyone else.

harg•1h ago
I believe the full docs page does indicate that there are binaries to install via popular package managers [1]

[1]: https://docs.jj-vcs.dev/latest/install-and-setup/

Philpax•28m ago
Immediately after that line:

> If you're not a Rust developer, please read the documentation to figure out how to install things on your platform

Rather selective reading we have here, don't we?

randyrand•59m ago
jj sounds awesome. I think I’ll give it a shot.

But I found this article a bit long winded and ended up asking an LLM about it instead.

jrockway•58m ago
jj is great and while it was an adjustment at first, I've never looked back. I feel like when you're working with other people, things never get reviewed and merged as quickly as you'd like. With jj, it's pretty low-cost to have a bunch of PRs open at once, and you can do something like `jj new <pr1> <pr2> <pr3>` to build stuff that requires all 3. This lets me do things like... not do a big refactoring in the same PR as adding a feature. I can have them both self-contained, but still start on the next step before they're all merged. It's easy to add changes on top, switching between the individual PRs as comments come up, etc.

I always liked doing things like this. At Google where we used a custom fork of Perforce, I told myself "NEVER DO STACKED CLs HAVE YOU NOT LEARNED YOUR LESSON YET?" If one CL depended on another... don't do it. With git... I told myself the same thing, as I sat in endless interactive rebases and merge conflict commits ("git rebase abort" might have been my most-used command). With jj, it's not a problem. There are merge conflicts. You can resolve them with the peace of mind as a separate commit to track your resolution. `jj new -d 'resolve merge conflict` -A @` to add a new commit after the conflicted one. Hack on your resolution until you're happy. jj squash --into @-. Merge conflict resolved.

It is truly a beautiful model. Really a big mental health saver. It just makes it so easy to work with other people.

andrewdea•8m ago
I'm having trouble understanding the value of this and most other supposed advantages of jj I'm seeing. I'm trying to pinpoint if it's because 1) my workflow doesn't need jj's fancy stuff, 2) I've gotten so used to `git`'s "flaws" that I don't notice them, or 3) the git porcelain I use (magit) does a good enough job at managing the flaws.

If you need to build on something that requires changes from 3 open PRs, can't you just start a new branch from main, merge all 3 PRs into it, and get to work? As changes are applied to the open PRs, you can rebase. Obviously that might cause some merge conflicts here and there, but as long as the PRs aren't super overlapping, they should still be manageable. If there's a ton of overlap between 3 open PRs, that to me sounds like a problem in the workflow/plan, which must be dealt with regardless of the VCS or porcelain.

wolttam•51m ago
What happens when jj introduces this native repository format - break compatibility with all the popular git hosts?

If jj is so great now and works with git as a backend, it’s tough to imagine why it’s worth pursuing a native and presumably incompatible backend.

kevin_nisbet•49m ago
I really wanted to like JJ, it was handy for a few months when I used it. But for me in the end I reverted back to regular git.

What triggered me to go back was I never got a really clean mental model for how to keep ontop of Github PRs, bring in changes from origin/main, and ended up really badly mangling a feature branch that multiple contributors were working on when we did want to pull it in. I'll probably try it again at some point, but working in a team through Github PRs that was my main barrier to entry.

steveklabnik•7m ago
This is good feedback, thanks. The next version of the tutorial will certainly focus on stuff like this, as I agree it's really important to teach people.
theappsecguy•42m ago
I'm still struggling most with the fact that my day-to-day work involves a git first platform like GitHub.

Although jj as a vcs system, it does feel better, working with git through it still feels like a chore, but to be fair I only gave it a day before going back to git.

Does anyone have any good resources on how to augment a git flow through the lens of a git hosting platform to work smoothly and still reap the benefits of jj?

r5Khe•28m ago
I'm not sure what the hangup is, TBH. I use `jj` with GitHub and ADO every day, and it works great.

What specific challenges are you running into that make it feel like a chore?

fallat•40m ago
Now that Steve is part of a GitHub competitor to push jj, I see all these posts as just sales pitches.
Philpax•39m ago
This tutorial predates his involvement with ERSC.
octocop•38m ago
Nobody is asking for a git replacement? I keep seeing these posts and I don't know who wants them.
SatvikBeri•35m ago
jj has almost 30,000 stars on github. You might not be looking for a different git ux, but plenty of people are!
vaylian•25m ago
You could have said the same thing about subversion.

Subversion is a fine VCS. But git offers a better approach with being offline-first and decentralized. It also makes merging branches a lot easier.

I don't know enough about jj to praise it, but I don't think git will be the last VCS that will become widely popular.

steveklabnik•20m ago
I wasn't asking. I loved git.

But then after trying jj, I wrote this tutorial because I love it even more.

alunchbox•28m ago
So glad to see this on HN, here to support it. JJ is amazing, the hardest hurdle was not the tool but the toolchain and ecosystem when I started ~ 2 years ago. It's grown rapidly and is incredible to see the community grow!
steveklabnik•27m ago
Hey folks!

So, I haven't updated the tutorial in a long time. My intent is to upstream it, but I've been very very busy at the startup I'm at, ersc.io, and haven't had the chance. I'm still using jj every day, and loving it.

Happy to answer any questions!

Openpic•23m ago
動画などでわかりやすいものが見たい
rs545837•21m ago
jj is genuinely great and I think it deserves way more adoption than it has right now. The mental model is so much cleaner than git, undo actually works the way you'd expect it to, and working with stacked changes feels natural instead of that constant low-grade anxiety of actually breaking something. It's probably the best frontend for version control that exists today.

For the last few months though I've been thinking a lot about what you said at the end there. What if version control actually understood the code it was tracking, not as lines of text but as the actual structures we write and think in, functions, classes, methods, the real building blocks? A rename happening on one branch and an unrelated function addition on another aren't a real conflict in any meaningful sense, they only look like one because every tool we have today treats source code as flat text files.

For enhancing this kind of structural intelligence I started working on github.com/ataraxy-labs/sem, which uses tree-sitter to parse code into semantic entities and operates at that level instead of lines. When you start thinking of code not as text there's another dimension where things can go, even a lot of logic at the comiler level with call graphs becomes useful.

Rare concert records going on Internet Archive

https://techcrunch.com/2026/04/13/thousands-of-rare-concert-recordings-are-landing-on-the-interne...
73•jrm-veris•1h ago•27 comments

What is jj and why should I care?

https://steveklabnik.github.io/jujutsu-tutorial/introduction/what-is-jj-and-why-should-i-care.html
292•tigerlily•4h ago•207 comments

The Future of Everything Is Lies, I Guess: Work

https://aphyr.com/posts/418-the-future-of-everything-is-lies-i-guess-work
15•aphyr•18m ago•7 comments

DaVinci Resolve – Photo

https://www.blackmagicdesign.com/products/davinciresolve/photo
833•thebiblelover7•12h ago•219 comments

A new spam policy for “back button hijacking”

https://developers.google.com/search/blog/2026/04/back-button-hijacking
599•zdw•12h ago•345 comments

NimConf 2026: Dates Announced, Registrations Open

https://nim-lang.org/blog/2026/04/07/nimconf-2026.html
69•moigagoo•4h ago•13 comments

Someone bought 30 WordPress plugins and planted a backdoor in all of them

https://anchor.host/someone-bought-30-wordpress-plugins-and-planted-a-backdoor-in-all-of-them/
1078•speckx•21h ago•304 comments

Backblaze has stopped backing up your data

https://rareese.com/posts/backblaze/
503•rrreese•6h ago•320 comments

GitHub Stacked PRs

https://github.github.com/gh-stack/
813•ezekg•18h ago•447 comments

The acyclic e-graph: Cranelift's mid-end optimizer

https://cfallin.org/blog/2026/04/09/aegraph/
27•tekknolagi•4d ago•4 comments

Introspective Diffusion Language Models

https://introspective-diffusion.github.io/
140•zagwdt•7h ago•32 comments

The M×N problem of tool calling and open-source models

https://www.thetypicalset.com/blog/grammar-parser-maintenance-contract
63•remilouf•5d ago•18 comments

Ransomware Is Growing Three Times Faster Than the Spending Meant to Stop It

https://ciphercue.com/blog/ransomware-claims-grew-faster-than-security-spend-2025
69•adulion•6h ago•57 comments

Show HN: Kontext CLI – Credential broker for AI coding agents in Go

https://github.com/kontext-dev/kontext-cli
4•mc-serious•1h ago•0 comments

The Case Against Gameplay Loops

https://blog.joeyschutz.com/the-case-against-gameplay-loops/
41•coinfused•3h ago•36 comments

Franklin's bad ads for Apple ][ clones and the beloved impersonator they depict

https://buttondown.com/suchbadtechads/archive/franklin-ace-1000/
78•rfarley04•3d ago•40 comments

Distributed DuckDB Instance

https://github.com/citguru/openduck
114•citguru•8h ago•25 comments

Lean proved this program correct; then I found a bug

https://kirancodes.me/posts/log-who-watches-the-watchers.html
322•bumbledraven•14h ago•147 comments

Nucleus Nouns

https://ben-mini.com/2026/nucleus-nouns
4•bewal416•4d ago•0 comments

Schools Never Taught Critical Thinking: AI Exposed the Lie

https://smarterarticles.co.uk/ai-exposed-the-lie-schools-never-taught-critical-thinking
44•dxs•49m ago•57 comments

The exponential curve behind open source backlogs

https://armanckeser.com/writing/jellyfin-flow
29•armanckeser•3h ago•16 comments

Multi-Agentic Software Development Is a Distributed Systems Problem

https://kirancodes.me/posts/log-distributed-llms.html
79•tie-in•9h ago•35 comments

WiiFin – Jellyfin Client for Nintendo Wii

https://github.com/fabienmillet/WiiFin
208•throwawayk7h•15h ago•94 comments

Show HN: Run GUIs as Scripts

https://github.com/skinnyjames/hokusai-pocket
8•zero-st4rs•4d ago•1 comments

MOS tech 6502 8-bit microprocessor in pure SQL powered by Postgres

https://github.com/lasect/pg_6502
54•adunk•9h ago•8 comments

Nothing Ever Happens: Polymarket bot that always buys No on non-sports markets

https://github.com/sterlingcrispin/nothing-ever-happens
456•m-hodges•23h ago•250 comments

The Great Majority: Body Snatching and Burial Reform in 19th-Century Britain

https://publicdomainreview.org/essay/the-great-majority/
15•apollinaire•3d ago•1 comments

A soft robot has no problem moving with no motor and no gears

https://engineering.princeton.edu/news/2026/04/08/soft-robot-has-no-problem-moving-no-motor-and-n...
59•hhs•4d ago•17 comments

US appeals court declares 158-year-old home distilling ban unconstitutional

https://nypost.com/2026/04/11/us-news/us-appeals-court-declares-158-year-old-home-distilling-ban-...
431•t-3•1d ago•304 comments

Lumina – a statically typed web-native language for JavaScript and WASM

https://github.com/nyigoro/lumina-lang
38•light_ideas•4d ago•16 comments