Top
Best
New

Posted by tigerlily 14 hours ago

jj – the CLI for Jujutsu(steveklabnik.github.io)
471 points | 404 commentspage 2
pheggs 8 hours ago|
I was already pretty happy with svn to be honest, I dont see myself switching away from the industry standard today for no substantial reason. in my opinion git was only able to change the standard thanks to github and a popular author (i love git and its branching, but I dont think it would have been enough if it was just for that). I personally believe its going to be very difficult for jj to replicate that.
GuB-42 7 hours ago||
In my opinion, svn lost to git because git is just so much better in a distributed environment. To me the improvement between git and svn is much more than the improvement between svn and cvs. In fact, by many aspects, I preferred cvs, but now that we have git, they can both go to hell.

Now, it is not the only DVCS, there is also Mercurial, which is built on similar principles. It could have become the standard, but I agree with you that the reason it didn't probably has to do with Github and Linux.

jj isn't fundamentally different from git, it is actually compatible with git, which is a good and a bad thing. Good because it makes transition easy, bad because it is fundamentally the same thing and there is no pressing reason to change.

But jj definitely look nicer than git, which is not hard, under the hood, git is great, but it is ugly. It started off as a hack and it still shows. I think the common sentiment of "I know git, I don't want to learn a new VCS" mostly tells about how painful the process of learning git was. If you had started off with Mercurial, like I did, I am sure it would feel much smoother, it is just git that is messy. For jj, it looks like they took the best parts of git and mercurial, so hopefully, the transition will be rather painless.

newsoftheday 8 hours ago||
I like the distributed nature of git but miss how svn worked to some degree. Generally I agree with you, git works, I read the post and didn't see anything that makes me want to change. The small number of jjites who have been inundating comment sections on this site lately feels like the devotees of Rust (a crap language), podman (which has too many operational inconsistencies) and JetBrains IntelliJ ballywhooers who used to preach IntelliJ's features on every programming related site.
kevin_nisbet 10 hours 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.

opem 4 hours ago||
I see that is an issue with many people, but now with github adding support for stacked PRs, I guess that would change
steveklabnik 9 hours 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.
p_stuart82 9 hours ago||
locally? sure. stacked changes in jj are great. but the moment you push to GitHub, the review UI still thinks in SHAs. a lot of the pain just moves from the author to the reviewer.
jrockway 10 hours 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 9 hours 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.

steveklabnik 8 hours ago||
For me, it wasn't so much that jj enabled things I couldn't do before, though there are some things. What it enabled was me doing the things I was doing, but in a more easy way. This also leads you to do things that you can do, but sometimes avoid because it's a lot of work.
andrewdea 7 hours ago||
I guess that makes sense but also reinforces the confusion I have on whether jj is just another git "porcelain" (aka UI), or a replacement for git altogether.

If it aims to mainly improve the UX (do the same things you were doing before but easier), then it's irrelevant to those of us who have been lucky to find and learn sensible UXs. If it aims to be a git replacement, I'm a little curious why the developers would decide to re-implement something from scratch only to end up with an "alternative" that is mostly compatible and doesn't radically change the internal model or add new features.

I last used GitHub Desktop years ago and had a terrible time. The git CLI is powerful but not very intuitive. It really wasn't until I learned magit that things "clicked" for me. I know that many git UXs are pretty bad. But the way git works internally seems pretty great to me. Too often, criticism of git conflates the two.

naasking 6 hours ago|||
> then it's irrelevant to those of us who have been lucky to find and learn sensible UXs

Only if you're a solo dev that doesn't work on a team or have to mentor new devs that haven't developed good intuitions for this.

This strikes me a lot like the C vs. safer programming language debate all over again.

andrewdea 6 hours ago||
When I mentor new devs, I explain to them how I use git. Sometimes I show them the workflow in magit, which makes it easier to visualize things. But mostly I just show them how their intended actions map onto the relevant CLI commands and I tell them to figure out how those map onto their porcelain of choice. I've developed this intuition thanks to magit, but I don't think magit is necessary. This approach seems preferable to me than onboarding new devs onto a new tool that is not the industry standard.

> This strikes me a lot like the C vs. safer programming language debate all over again.

I don't see how. Safer programming language address a clear problem in C, with trade-offs (sometimes arguably the trade-offs may not be worth it, and in my experience that's what the debate tends to be about). If jj is a replacement for git it should be clear what problem within git it aims at addressing. If the problem is in the UX, then to me and many others it's not worth the trouble.

naasking 5 hours ago||
> When I mentor new devs, I explain to them how I use git.

Now imagine not needing to do that.

> I don't see how. Safer programming language address a clear problem in C

Being productive in C means training and experience in avoiding the footguns of C. See above.

steveklabnik 6 hours ago|||
Fundamentally, jj is its own VCS. It's just that it has pluggable backends. So when you use it with the git backend, it functions as a nicer git UI, but it's also not just that, because you can use it without git entirely. (though the major alternative backend is not open source, so while people do, unless you work at Google (or the startup I'm at...) you may personally not be able to.)

> then it's irrelevant to those of us who have been lucky to find and learn sensible UXs.

I was never someone who was upset at git's UX. I never found the 'hg is so much nicer' thing compelling. But then, I found that jj is just so much nicer to use, for me, that I haven't used git itself in years at this point. But it's also true that if you like using git, and want to keep using it, that's fine! The wonderful thing about the interop here is that I can use jj, and you can use git, and we're all good.

> I'm a little curious why the developers would decide to re-implement something from scratch only to end up with an "alternative" that is mostly compatible

Realistically, with git's dominance, compatibility is the only way that you get people to actually try out your thing. I know I wouldn't have given it a shot unless I could use it with a git repo.

> or add new features

I mean, there's two things here: one of which is, jj does have new features. I described the ability for a jj repo to exist in a conflicted state upthread, for example. jj undo is a godsend. But at the same time, at the end of the day, when you're trying to manipulate a graph of changes, there's always some way to end up in the same end state with git, because, well, you're trying to interoperate. So you can sort of handwave away a lot of features with a kind of "well I can do that in git via <totally different means>", and sure, that's true in a sense, but tools affect the way you work. I'm much more effective with jj's model of the world than I was with git's, even though I didn't actively feel that pain until I tried jj.

> It really wasn't until I learned magit

Ah, you use magit! So yeah, like, jj is like magit in the sense that it lets you interact with a git repository in a different way than the standard tool. And that's useful. I never would have used magit because I don't use emacs. (and there are some folks trying to do "magit but for jj"...)

> But the way git works internally seems pretty great to me. Too often, criticism of git conflates the two.

I agree, in general. I do think that there are still good criticisms to be made, but a lot of it is uninformed. Just how things go.

skydhash 5 hours ago||
> Ah, you use magit! So yeah, like, jj is like magit in the sense that it lets you interact with a git repository in a different way than the standard tool. And that's useful. I never would have used magit because I don't use emacs.

I also use magit and I was confused by the "advantages" that jj has over git. The nice thing about magit is that it doesn't hide git. What it does add is easier typing of the flags (using transient), completions of arguments like branch names (using Emacs), DWIM behavior depending on cursor position and region selection (especially for commit hashes). Also it has nice presentation of the information which acts like hubs for all the above.

I guest jj makes sense if you're using the cli directly. But with magit, every operation is only a few keystrokes. It is to git, what vim is to editing. And I could probably cobble something close with tig or lazygit if I switched from emacs.

Aperocky 8 hours ago||
With agents, my go to is now have multiple of the same repository and each agents must work on a separate one.

Preventing dirty workspace by solving the co-work problem to start with. merges are much more trivial than trying to make agents remember which branch or which folder it is supposed to work on. Disk space is cheaper than mental anguish and token usage.

chriswarbo 8 hours ago||
https://git-scm.com/docs/git-worktree
rattray 8 hours ago||
What's your naming scheme?
Aperocky 8 hours ago||
REPO_NAME_0

REPO_NAME_1

REPO_NAME_2

REPO_NAME_3

justinmayer 10 hours 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 10 hours ago|
jjui TUI is incredible also
rs545837 9 hours 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 https://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.

sieabahlpark 9 hours ago|
[dead]
dmitshur 5 hours ago||
What is the current story for serving jj repositories over HTTPS? Git has https://git-scm.com/book/ms/v2/Git-on-the-Server-The-Protoco... . Does jj have something better, equivalent, or nothing (at this time) at all?
steveklabnik 5 hours ago|
Unless you're at Google (or writing your own backend), jj talks to a git server, and so you'd just do exactly that: host a git repo over https.
shuyang 12 hours 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 12 hours ago||
I wonder if the recent github stack system could help with that (https://github.github.com/gh-stack/guides/ui/)
shuyang 12 hours ago||
waitlist only :/ waiting to get in so i can test it out!
nerdypepper 11 hours 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...

joshka 11 hours 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 11 hours 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 :(

saghm 10 hours 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.
bananapub 12 hours ago||
github added support for this in the last six hours - https://github.github.com/gh-stack/faq/#will-this-work-with-...
misnome 8 hours ago||
The problems with jj that led me to abandon are:

- All of everything good about it breaks down the instant you want to share work with the outside world. It's git on the backend! Except there isn't any concept of a remote jj so you have to go through the painful steps of manually naming commits, pushing, pulling, then manually advancing the current working point to match. And in doing so, you lose almost everything that gives it value in the first place - the elegant multi branch handling, anonymous commits, the evolog. Even if you want to work on the same project on two machines your only choice for this is without breaking everything via git is to rsync the folder. Yes, you can write alias to do all this like git. I might as well use git if I can't use the nice features.

- All files automatically committed is great until you accidentally put a secret in an unignored file in the repository folder. And then there is no way to ensure that it's purged (unlike in git) - the community response as far as I can tell is "Don't do this, never put a file that isn't in gitignore".

- And adding to .gitignore fails if you ever want to wind back in history - if you go back before a file was added to .gitignore, then whoops now it isn't ignored, is all part of your immutable history, and disappears if you ever switch off of that new commit state.

waynecochran 9 hours ago|
Anything new or special in jj that allows me to work with large binary files simply? To me, this is still unsolved in terms of providing an elegant solution (e.g. things like Git Large File Storage (Git LFS) are awkward).
brendoncarroll 9 hours ago||
I've heard that jj has support for non-git backends? Can anyone comment on how difficult it would be to add support for another backend, any docs or examples?

I have a project[0] that does the large file thing well, but is missing most of the version control porcelain. I've been looking for the path of least resistance to integrate it into something with a larger user base.

[0] https://github.com/gotvc/got

steveklabnik 8 hours ago||
To add a new backend, there's a trait that you implement for your backend: https://github.com/jj-vcs/jj/blob/713a0d0898448392d38fdcbaba...

I suspect if you came by the jj discord, folks could help you with more detail than that.

brendoncarroll 8 hours ago||
Thanks for the link.

It looks like this treats files as blobs just like Git, and trees as single objects which fit in memory. Assuming that is a correct understanding, this core abstraction would need to change to handle large files and directories well.

All the well known version control systems do this though, and it simplifies the system significantly. It's the right model for source code, but it doesn't translate well to arbitrary data.

steveklabnik 7 hours ago||
Yes, it will require work to do large files well. But there is general interest in upstream in having that, there's just nobody driving the work at the moment.
steveklabnik 9 hours ago||
Not yet. It's desired to do something better here, but there's no active development that I'm aware of right now.

(LFS support is in progress though)

More comments...