Most active commenters
  • steveklabnik(8)
  • Vinnl(3)

←back to thread

I see a future in jj

(steveklabnik.com)
291 points steveklabnik | 51 comments | | HN request time: 1.286s | source | bottom
1. kelnos ◴[] No.45673281[source]
At the risk of being unreasonably negative, stuff like this just makes me feel... tired. Git is... fine. I'm sure it doesn't solve every problem for everyone, and oh boy does it still have many rough edges, but it works and (as the article points out), git has won and is widely adopted.

I've extensively used CVS and Subversion in the past. I touched Mercurial and Bazaar when I ran into a project that used it. I remember in the CVS days, SVN was exciting to me, because CVS was such a pain to use, in almost every way. In the SVN days, git was exciting to me, because SVN still had quite a few pain points that poked me during daily use. Again, yes, git had and has rough edges, but nothing that would make me excited about a new VCS, I don't think.

Maybe I'm just getting old, and new tools don't excite me as much anymore. Learning a new tool means spending time doing something that isn't actually building, so my eventual use of the new tool needs to save me enough time (or at least frustration, messily converted into time units) to balance that out. And I need to factor in the risk that the new tool won't actually work out for me, or that it won't end up being adopted enough to matter. So I think I'll wait on jj, and see what happens. If it ends up becoming a Big Deal, I'll learn it.

replies(10): >>45673426 #>>45673659 #>>45673916 #>>45673995 #>>45674049 #>>45674219 #>>45674653 #>>45674662 #>>45675434 #>>45676064 #
2. steveklabnik ◴[] No.45673426[source]
I think being conservative about tool use is totally fine! I'm actually pretty conservative about most of the tools that I use.

The goal of this post wasn't really to convince anyone on why they may want to give jj a shot, more of just a post about how I think about technologies I may want to spend my limited time on this planet working on, and announce that I'm making a move.

I don't think that you're being unreasonably negative. I think it's crucial for technologies to understand that your position is basically the default one, and that you need to offer a real compelling reason to choose a new tool. For some people, jj has enough of that already to bother with choosing, but I think the real power is in things that aren't widely available yet. Hence the need to go build some stuff. It's early days! Not even 1.0 yet. It's very natural that most people do not care at this stage.

replies(2): >>45673620 #>>45673767 #
3. jimbokun ◴[] No.45673620[source]
One thing not mentioned in the article: what advantages does jj offer over plain git?
replies(1): >>45673808 #
4. pythonaut_16 ◴[] No.45673659[source]
Fair points. I'm also generally happy with Git myself.

I've been exploring JJ mainly for its slightly different approach to change tracking (~every change gets tracked, at least initially, rather than just commits).

Stacked PRs also look interesting but I haven't had an occasion to try them out yet.

5. kelnos ◴[] No.45673767[source]
Sure, definitely, sorry for being a bit off-topic, clearly this was about you and your plans and not intended to be about jj itself.

Having said what I said, I do find new tools to be interesting, and I do hope jj ends up being successful. I'm always happy to be surprised by something that fixes problems that I didn't consciously know I had, or that adds new features or work modes that make my life easier in ways that never would have occurred to me in the first place. I was a pretty early git adopter, and it works great for me, but I'm sure a decent chunk of that is because I understand how it works under the hood, even if it often doesn't present a great UX.

And even if jj doesn't eventually surpass git's popularity, it's great to have other options, and avoid monocultures.

6. steveklabnik ◴[] No.45673808{3}[source]
So for me, the most compelling thing about jj is that it is somehow simpler than git, while also being more powerful than git.

What I mean by simpler is, there's fewer features, which makes things easier to pick up, because these features fit together in a way that's more coherent than git's. By more powerful, I mean jj lets me regularly do things that are possible, but annoying and/or difficult in git.

I loved git. I was never the kind of person who thought its CLI was bad. But then, when I found jj, I realized why people thought that.

replies(5): >>45673846 #>>45673901 #>>45674170 #>>45674695 #>>45677921 #
7. jimbokun ◴[] No.45673846{4}[source]
So better UX while keeping git's solid internals?

Makes sense. Developers I know have been wanting that.

replies(2): >>45673923 #>>45674368 #
8. wk_end ◴[] No.45673901{4}[source]
As someone who loves git, has always thought the criticisms about its interface were overstated... but also feels like it maybe has too many incoherent ways of doing things, this is the best sales pitch I could've asked for (and I came to the comments to ask for a sales pitch). Thanks - I'll try jj out the next time I start a hobby project.
replies(2): >>45674078 #>>45675132 #
9. jakub_g ◴[] No.45673916[source]
The good thing is that a new player entering the arena allows a fresh look at certain problems, and some solutions then get backported to the OG project. I've read it already happened that jj inspired some changes in git.

Same happened e.g. with nodejs getting deno and bun around, which allowed to break nodejs' inertia on many problems that the others have solved.

10. steveklabnik ◴[] No.45673923{5}[source]
It's technically a bit more than that. JJ is its own VCS, with pluggable backends. Google has a closed-source Piper backend, the git backend is the only real open source backend. But at high level, it's fine to think about it in that way, yeah. I tend to think about it as being more "able to work on git repos" than as a UI.
replies(1): >>45674448 #
11. baq ◴[] No.45673995[source]
I used to think this, too. Tried jj a few times before it clicked.

It’s very liberating in some ways, in others it’s simply no worse than git. You can do everything you can do with git, but some of those things don’t require multiple steps or n repeats of the same action. jj rebase + commitable conflicts + jj undo = freedom and peace of mind.

12. weinzierl ◴[] No.45674049[source]
I used to think the same way about jj not too long ago. I even wrote a few comments here similar to yours, but since then I’ve changed my mind.

For me, the turning point was realizing that jj actually eased some of the frustrations I had with our rebase workflow at work. It took a while for it to click, but now I wouldn’t want to go back

replies(1): >>45674498 #
13. steveklabnik ◴[] No.45674078{5}[source]
You're welcome, and feel free to let me know how it goes. There is an adjustment period, for sure, and (in another eerie parallel to Rust) some folks try it, bounce off, and try again later, and it sticks then.

The auto-commit behavior was one of my biggest concerns when starting, but it turns out that when combined with other things, I'm a huge fan now, for example.

14. nonethewiser ◴[] No.45674170{4}[source]
can you directly get the parent branch of a branch in jj?

This is one thing that I constantly find myself wishing was in git but inevitably resign myself to knowing "thats just not how git works."

replies(4): >>45674440 #>>45674578 #>>45674608 #>>45678954 #
15. dxdm ◴[] No.45674219[source]
I think yours a perfectly reasonable stance, and I often feel the same way. And all this complaining about git is getting tiresome, especially if you had to deal with its predecessors.

FWIW, I still tried out jj and found it a joy to use. I use it all the time now. Most of the time, it not only gets out of your way, but rolls out the red carpet. I'm saying that as someone who knows their way around the git command line. t's like replacing your trusty old remote control with a new one where the buttons are well labeled, ergonomically placed, that lets you do entirely new useful things, and it has a universal back button that just works.

Maybe jj is an especially good fit for my way of working, but I do think that it is a real, actual improvement for everyone.

And it's super easy to pick up anytime. So yeah, I think you're doing it right! Sit back and let it come your way. From what I can see, there's a pretty good chance that it will.

16. SoftTalker ◴[] No.45674368{5}[source]
Not the only project that's working on that.

https://www.gameoftrees.org/

17. steveklabnik ◴[] No.45674440{5}[source]
Could you spell out slightly more what you mean? I'm not 100% sure what "get" means.
replies(1): >>45674700 #
18. warwren ◴[] No.45674448{6}[source]
I can't hear Piper backend without thinking about Pied Piper
19. riffraff ◴[] No.45674498[source]
May I ask what is your rebase workflow at work?

In my day to day, its basically "git pull --rebase repo branch", plus some interactive rebate to squash commits, and it's not particularly frustrating, so I'm curious what you're doing that we're not.

replies(1): >>45674687 #
20. baq ◴[] No.45674578{5}[source]
I don’t think you ever need to do this, jj tracks changes much better than git, assuming I understand your question. E.g. you can rebase a whole local change dag based on a commit from origin with a single jj rebase -b and it’ll move bookmarks (git branches) correctly.
21. mckn1ght ◴[] No.45674608{5}[source]
Right, “parent branch” implies a tree structure, but git is a DAG.

You might have a specific workflow such that you can actually answer your question, but it won’t generally apply to all repos.

Since a branch is really just a label for a specific commit, which may be at the end of a chain of successive parent commits, a branch isn’t really a first class structure, but a derived one.

You can get the fork point of a branch, which is a common ancestor commit shared by another branch, but that fork point is a commit and may not have a branch label. That commit can have any number of other branches going off of it: how would you decide which one is the parent vs just another sibling?

My assumption after looking at jj is that it is not as complicated as git yet. Give it time. It’s also not even as simple as git for many tasks, based on their own docs: https://jj-vcs.github.io/jj/latest/git-command-table/

22. kzrdude ◴[] No.45674653[source]
I learned all of cvs, svn and then later git when getting into Linux and Open Source. Based on my early experience of multiple systems, I'm very surprised that git has dominated and lasted this long already!
23. jrockway ◴[] No.45674662[source]
jj is actually so good though. People don't need to know you're using it, which is why it's nice.

A problem I run into when working with other people is that code reviews take forever and I need to build on top of them. Code gets merged while it's being reviewed, and it becomes a burden to keep rebasing your stack of PRs. It's also difficult to do things like designing each PR against the main branch, but testing all 3 of them together. (Sometimes you want to write the docs / take screenshots as though all your features are merged as-is.) jj makes all this trivial. You tell it what you want and it does it without involving an index or working copy or interrupting you to resolve conflicts.

I've found that it really makes me less annoyed when working with other people. I don't know why it takes people longer to review code (or to even open the review request) than it takes me to write things. But it does, and jj is what keeps me sane.

To be fair, I also use it on personal projects because sometimes you have 3 things you want to try at once and they're not related to each other. Upstream isn't going to change without your understanding, but it's still mechanically something to maintain the rebases on those 3 branches. jj just makes this burden go away.

Having said that, I don't know why a "jjhub" is needed. Github seems fine. jj's just a UI for git.

replies(3): >>45674881 #>>45675362 #>>45676342 #
24. weinzierl ◴[] No.45674687{3}[source]
Basically the same except in some projects we are not supposed to squash. So, sometimes we end up with long long histories to be rebased onto other long histories.

rerere only helps so much with conflict resolution but with jj I think it is as painless as it could be.

25. petre ◴[] No.45674695{4}[source]
Git's CLI is awful compared to fossil or even mercurial. Jj seems like an improvement over git, but it lacks a web UI like fossil has. It's very useful. Basically like a self contained github lite, only without the needless complexity, the enterprise bs, the annoying login process, tokens, passkeys, brain damaged permissions system etc.
26. 1718627440 ◴[] No.45674700{6}[source]
I think they mean what other branch some branch was originally branched off from.
27. constantius ◴[] No.45674881[source]
I have a question and you might have an idea about this:

I have a workflow where I have my main and a bunch of branches that are children of other branches. So: main, branch_a, branch_a_1, branch_a_2, branch_a_1_x, etc. Probably not a good workflow, but that's what I do.

I keep editing old commits in my branches to have clean, atomic commits, which fucks up my branch structure and I need to cascade-rebase everything manually.

Do I understand correctly that jj does it automatically?

replies(1): >>45674973 #
28. steveklabnik ◴[] No.45674973{3}[source]
That's correct, it will do the cascade rebase of everything automatically.
29. lowboy ◴[] No.45675132{5}[source]
Another good sales pitch is `jj undo`[0]. It puts the repo back to previous state, regardless of what the mutative operation was. It's a powerful and simple safety net that unlocks experimentation.

It does this by adding an new operation on top of the operation log[1], so you don't lose repository states by moving up + down the op log. There's a corresponding `jj redo` as well.

0: https://jj-vcs.github.io/jj/latest/cli-reference/#jj-undo

1: https://jj-vcs.github.io/jj/latest/operation-log/

replies(1): >>45675737 #
30. conradludgate ◴[] No.45675362[source]
I use git but I instead just keep all PRs stacked on top of each other and rebase when one is merged. If something is easy to review I push it down the stack. If something is harder to review I keep it at the top of the stack.

I don't open a PR for each commit, and we use squash commits at work which makes it harder to have this workflow but it still works fine for me.

I rebase only the leaf PR, and I have update-ref enabled to update the branch refs of all other branches in the stack. It works well. The only manual process is that I have to manually force push each branch afterwards.

Lastly, I use the `-x "cargo fmt" -x "cargo clippy"` feature when rebasing (which is missing in jj) to make sure the stack stays in a good state

replies(1): >>45678033 #
31. kolme ◴[] No.45675434[source]
I've also worked with CSV (barely) and SVN (more extensively) and I was blown away by Git.

You can have real branches! Many of them! You don't have to manually merge them! It's decentralized, you can have multiple origins, it lets you work offline! The list goes on and on.

There were many compelling reasons to switch to Git. But for all the articles about jj out there, I've never read any compelling reason to switch to jj. "It easier", "the commands are somewhat more ergonomic"... that's all?

replies(2): >>45675571 #>>45676025 #
32. turtlebits ◴[] No.45675571[source]
Ergonomics are everything. Its why there are zillion IDEs, terminal apps, keyboards, mice, etc.

Hot take, but I personally hate git and almost always rely on a GUI tool or IDE integration to interact with it.

33. socalgal2 ◴[] No.45675737{6}[source]
jj undo is great but it's a one time thing. You can't do jj this, jj that, jj other, jj undo, jj undo, jj undo AFIACT. You have to look into the op log and jj op restore for that. It's nice you can get back to where you were though.

The biggest issue for me is it requires active change management (or feels like it). In git I do `git checkout foo` then I start editing. If I want to see what may changes are since foo then `git diff` tells me. With jj though, `jj edit foo` is the to git, state of the repo ALL changes to foo. So any new edits are invisible. So, instead of `jj edit` I have to do `jj edit` `jj new`, then later squash those into foo

I know there are similar cases in git but I guess I'm just used to git so I wasn't using those cases.

that said, I'm mostly enjoying jj. Though quite often i get a conflict I don't understand. Today I got 2 and it told me choose A or B. I did `jj diff -r A -r B` and it said no diffs. If no diffs aren't there no conflicts? I'm sure someone gets it but it was annoying to just have to pick one to abandon

replies(3): >>45675972 #>>45676015 #>>45676061 #
34. mkeeter ◴[] No.45675972{7}[source]
> jj undo is great but it's a one time thing.

For what it's worth, this changed in v0.33.0:

> jj undo is now sequential: invoking it multiple times in sequence repeatedly undoes actions in the operation log.

(release notes: https://github.com/jj-vcs/jj/releases/tag/v0.33.0)

35. steveklabnik ◴[] No.45676015{7}[source]
I’m not sure if it’s a typo, but you don’t need to edit and then new, you can just new. It’s a good habit to get into as a replacement for checking something out.

I’m not sure what happened in your conflict situation either, that does sound frustrating. EDIT: Oh, I wonder if it was this: https://jj-vcs.github.io/jj/latest/technical/concurrency/ specifically, that I bet the repo was being modified concurrently, and so you ended up with a divergent change.

36. dagenix ◴[] No.45676025[source]
One thing JJ has that git doesn't is the concept of first class conflicts. In JJ, rebasing or merging never fails, but it might record a conflict to resolve later. Git, on the otherhand, forces you to drop we everything to resolve conflicts immediately. It sounds like a small thing - but in my experience, being able to resolve conflicts later when I feel like it is absolutely amazing and really helps reduce context switching.
37. lowboy ◴[] No.45676061{7}[source]
> You can't do jj this, jj that, jj other, jj undo, jj undo, jj undo AFIACT

You can as of v0.33.0[0]. Previous behaviour was that `jj undo; jj undo` would leave you where you started (it undid the undo).

> The biggest issue for me is it requires active change management (or feels like it). In git I do `git checkout foo` then I start editing. If I want to see what may changes are since foo then `git diff` tells me. With jj though, `jj edit foo` is the to git, state of the repo ALL changes to foo. So any new edits are invisible. So, instead of `jj edit` I have to do `jj edit` `jj new`, then later squash those into foo

I'm not 100% clear on what you mean here, but a few things that might help:

1. In jj you don't "checkout" a branch, you edit a specific commit. That commit might be pointed to by a bookmark but it doesn't have to be. A jj bookmark is roughly equivalent to what git calls a branch. Note that a git branch, and a jj bookmark are just pointers to a commit, as illustrated here[1]).

2. If you want to resume work on a branch/bookmark instead of `git checkout BRANCHNAME` you'd do `jj new BRANCHNAME` which puts a new commit on top of the commit and sets it as a working copy.

3. Bookmarks don't auto advance like they do in git. So adding new commits on top of a "branch" will leave the bookmark where it is until you `jj bookmark set/move` it. So you could squash commits down into the "foo" bookmark, but you could also move "foo" to point to subsequent commits.

4. Not sure what you mean by edits being invisible, but if it's seeing a diff from main to the tip of your branch (with a change id of ex. XYZ) it would be `jj diff -f main -t XYZ`.

0: https://github.com/jj-vcs/jj/blob/main/CHANGELOG.md#0330---2...

1: https://social.jvns.ca/@b0rk/111709462585184810

38. jauntywundrkind ◴[] No.45676064[source]
I personally feel quite capable at git and am not looking for another flow or tool.

But. I think it's incredibly useful for organizations to have patterns for how they use git. There can be huge variance! And there's so many people who don't feel comfortable doing interactive rebases (of their feature branches), or other serious monkeying with history.

(I also think jj's flows are incredibly good about avoiding accidental loss of work in a way that git can be extremely dangerous at.)

I think there's a ton of value to having more of a pattern than the free-form jamming that git gives us. The real value I see in jj is that it's more than the toolbox of things git gives one: it's something more learnable, teachable, and directed than git. And it seems to do it pretty well, with style, and less monkey business. I'm still super greenhorn at jj, and honestly lacking the need for it, but I'm excited to see it come along. Especially since it is compatible with so many other VCS.

39. Vinnl ◴[] No.45676342[source]
> Having said that, I don't know why a "jjhub" is needed. Github seems fine. jj's just a UI for git.

When you make a change to a pr in response to review feedback, do you just jj edit it in, and end up with a force push on GitHub? After which the review comment might get detached from the code or even hidden.

That's definitely something that could be better for me. (That said, there are other projects making it better too.)

replies(2): >>45676415 #>>45676487 #
40. jrockway ◴[] No.45676415{3}[source]
Yeah, I always force push. I always treat PRs as one atomic unit ("squash and merge") and the history that goes into the PR isn't relevant to me after it's merged. Maybe once or twice I've regretted this (maybe you want to backport one part of this PR to the release branch, and now you have to manually create that) but in general, how something is made can be ugly and it feels good to me to erase it when something is ready to be merged.
replies(2): >>45677721 #>>45679143 #
41. noirscape ◴[] No.45676487{3}[source]
Without knowing much about jj, isn't this more of a problem in how the GitHub/GitLab/Forgejo Pull Request system works rather than a jj problem?

Patch-based workflows in general (where you heavily use git rebase -i to curate a smaller set of "perfect" commits for anything you'd PR, rather than just piling new commits onto every PR) don't work well with the GitHub approach, which heavily favors merging stuff through the web interface (making merge or squash commits along the way).

You can make it work of course, but GitHub tends to behave in weird ways when it comes to how it's interface works with patch-based workflows. Perhaps a better estimate would be to see how it compares to a forge like Phorge or Sourcehut.

replies(1): >>45679130 #
42. jjmarr ◴[] No.45677721{4}[source]
I'm banned from force-pushing at work so this makes jujutsu a challenge for me.

The workflow still functions, it just requires me to manually update bookmarks.

43. zZorgz ◴[] No.45677921{4}[source]
Just my feedback - I've personally found jj more complex for simple projects. Like if you have a non-collaborative repo where you push to main most of the time after making a series of commits, in jj you have to keep updating a bookmark before pushing it and there's no one command to do both.

If you have another machine on main without any outstanding changes and you want to pull the latest changes that is probably also two steps (git fetch + new?)

That said, I've been liking jj quite a bit for more mature / collaborative projects. It has been a learning experience. (don't enjoy updating bookmarks for PR branches though; jj encourages rewriting history which is not my favorite choice for code review branches; I often work in repos that squash-on-merge).

replies(1): >>45677946 #
44. steveklabnik ◴[] No.45677946{5}[source]
Yeah, in that case you may want to configure bookmarks to auto update for sure :)
replies(1): >>45678147 #
45. ricericerice ◴[] No.45678033{3}[source]
i believe `jj fix` is your -x equivalent, though im not familiar enough with it to comment on how similar the semantics actually are
replies(1): >>45678600 #
46. zZorgz ◴[] No.45678147{6}[source]
Is there a way to do that today?

For updating bookmarks I've found like half a dozen variants of `tug` alias the community has come to using which is just a slight improvement (bit daunting to newcomer to pick 'best' one and not fan setting up aliases on all my working devices).

It would be nice if jj was better than git for the fundamental workflows like this out of the box overall.

47. conradludgate ◴[] No.45678600{4}[source]
It is not even close to sufficient. jj fix only executes the command on one file at a time (only the changed files) so it can't work on anything that has linter semantics.

jj does this for performance reasons. They don't want to perform a full checkout for every rebase action. This is simply something I disagree with

replies(1): >>45678739 #
48. martinvonz ◴[] No.45678739{5}[source]
> jj does this for performance reasons. They don't want to perform a full checkout for every rebase action.

It's true that `jj fix` can be faster by not touching the working copy, but we also want a `jj run` command for the linter feature (https://github.com/jj-vcs/jj/issues/1869). It's just not done yet.

49. KingMob ◴[] No.45678954{5}[source]
That's even less how jj works, unfortunately for this use case, because jj doesn't require branches to be named.

You could probably attach metadata to commits indicating the branch name at time of creation, but there's probably a lot of weird edge cases to handle.

50. Vinnl ◴[] No.45679130{4}[source]
Yes, that's why I asked it as a response to them saying GitHub was just fine :) With Git, I work around it by adding `--fixup` commits and then doing a final `git rebase --autosquash` just before landing it, but it would be nice to have a better workflow.

(The mention of the GitHub SVP being interested in stacked diffs sounds good in that regard. I'm also keeping an eye on Tangled and, now, on ERSC.)

51. Vinnl ◴[] No.45679143{4}[source]
I guess in terms of clean workflow, I could get into that more using jj (i.e. create a PR for every bit that I want to have in the history later), but as a reviewer, I always get annoyed when I have to do a re-review of something that was force-pushed, and I'd like to avoid doing that to others. So I was kind-of hoping you had found some magical silver bullet there, haha.