17 ms·
Jujutsu for everyone
- marcuskaz 1y ago> Jujutsu is more powerful than Git. Despite the fact that it's easier to learn and more intuitive, it actually has loads of awesome capabilities for power users that completely leave Git in the dust. Like? This isn't explained, I'm curious on why I would want to use it, but this is just an empty platitude, doesn't really give me a reason to try.
- jennyholzer 1y agoI agree. I'm willing to give them the benefit of the doubt to some extent because existing Git UIs are pretty poor in my opinion. But I'd like to see some more meat on the bone, in particular a demonstration of why this is easier/more powerful/more convenient to use than the alternatives.
- tcoff91 1y agoThe main thing that makes it more powerful imo is that you can accomplish insane rebases with 1 command that would be really difficult with git. Like let’s say you have 4 separate PRs in review that have no dependency on each other. You then work on new stuff on top of an octopus merge of all 4. You are exploring different approaches to a solution so you have several anonymous branches where you have tried different things. You want to rebase on master, so you just run jj rebase -d master. All 4 PR branches, the octopus merge, the anonymous branches, they all get rebased with that 1 command. If there are conflicts the first class conflicts mean that you can fix the conflicts whenever you want. If one of your experimental anonymous branches is in conflict but you are unlikely to go with that approach, just leave it in a conflicted state unless you change your mind that you want to actually go that direction.
- kyrra 1y agoOne example: Merge conflicts can be submitted as a proper entry and dealt with later: https://jj-vcs.github.io/jj/latest/conflicts/ https://jj-vcs.github.io/jj/latest/conflicts/
- senekor 1y agoHi, author here. Since the target audience is people with little to no Git experience, a detailed comparison would not make sense. I did simply make that claim because the weirdness of Git's UI is usually justified by saying how powerful it is. So this statement is just intended to ease the readers mind that they're not missing out on power by choosing a tool that's easier to learn.
- jennyholzer 1y agoI appreciate this perspective. IMO, the authors and evangelists of Git are essentially correct when they argue about its power. However, I think that it's extremely difficult to gain practical experience with using Git in a high-powered, high-agency way, mostly because there are a lot of abstract concepts at play and there is no easily accessible place where these concepts can be "discovered". Basically, Git is as good as it's cracked up to be, but only if you're an expert. If you're interested in becoming a Git expert, I cannot recommend Emacs Magit strongly enough. If not, I think Jujutsu could be an quicker road to a high-agency version control workflow. It's at least worth considering. I feel confident that Jujutsu can succeed, in particular because of Git's harsh difficulty curve.
- senekor 1y agoThanks, but I consider myself a Git expert already :-) I read the Pro Git book cover to cover. I have a gluten-free, artisanal, free-range git config that I've grown and cared for over years. single character aliases all the important commands, "log all graph oneline", "commit amend no-edit", interactive rebase (ofc. with autosquash, autostash, updaterefs and rebasemerges), reset hard, push force-with-lease... Also: commit signing, url rewriting, conditional configs for different orgs, all that jazz. I was super productive with it and loved it. And then Jujutsu came along and casually doubled my VCS productivity. I didn't see it coming!
- nocman 1y agoIs there a particular pain point (or set of pain points) that you have using git which is removed when you use Jujutsu? I am interested to know, because there seem to be a small number of people who really seem to like it, and up to this point I haven't been able to understand what it is that they are all so excited about.
- pkulak 1y agoSay you start on Main, then make a new branch that you intend to be a PR someday. You make commit 1. Then another. Maybe 6 more. Now you realize that something in commit 1 should have been done differently. So, you "edit" commit 1. All the other commits automatically rebase on top and when you go back to your last commit, it's there. Same with _after_ you PR and someone notices something in commit 3. Edit it, push, and it's fixed. You can do all that in Git, but I sure as hell never did; and my co-workers really appreciate PRs that are broken into lots of little commits that can be easily looked over, one by one.
- lrobinovitch 1y agoYou have to force push each time you do this, right? How do your coworkers find the incremental change you made to commit 1 after you force push it, and how do you deal with collaborative branches effectively this way? And if I don't want to work this way and force push, are there other benefits of jj?
- baq 1y agothe heuristic is 'if you know about rerere and especially if you use it, you should try jj'. if you never force push, you might not see value in jj. (I basically always force push.)
- lrobinovitch 1y agoThat makes sense, good to know, thanks. > I basically always force push How do your colleagues deal with this, or is this mostly on experimental branches or individual projects?
- whateveracct 1y agoPeople barely ever work off my branches.
- smw 1y agoIt's generally fine if you force push a branch that you're the only one working on. In many projects, there's an expectation that the 'PR Branch' you create in order to make a github pull request is owned by you, and can be rebased/edited/force-pushed at will. It's very common to do things like `git commit --amend --no-edit` to fix a typo or lint issue and then force push to update the last commit. This has it's problems, and there's a reason things like Geritt are popular in some more sophisticated shops, as they make it much easier to review changes to PRs in response to reviews, as an example.
- interroboink 1y agoJujutsu has many Mercurial-style features, one of them being revsets[1] - a set-notation-style DSL for selecting changesets (eg: which ones to log, etc). I have never found anything as powerful as revsets in Git.[2] [1] https://jj-vcs.github.io/jj/latest/revsets/ https://jj-vcs.github.io/jj/latest/revsets/ [2] https://stackoverflow.com/questions/22520751/what-is-the-git-equivalent-of-mercurial-revsets https://stackoverflow.com/questions/22520751/what-is-the-git...
- capitainenemo 1y agoYeah, I'm excited by the mercurial-style features as a mercurial user looking for something to transition to in a world where git has, sadly, become the standard. The revsets were definitely a joy to discover. The main thing I'm hoping they add is mercurial's diff format which, according to the jujutsu dev discussions, is considerably better than git's, and allows for cleaner "absorb" and, apparently, the clearness of mercurial's "hg fa --deleted". And, well, it's silly, but I do like revnums. It's a compact way to compare changes over time, even if it's only useful for the local repo. Would be nice to have those too.
- exclipy 1y agogit-branchless implements revsets for git https://github.com/arxanas/git-branchless/wiki/Reference:-Revsets https://github.com/arxanas/git-branchless/wiki/Reference:-Re...
- MrJohz 1y agoGit branchless is basically jj as a git subcommand - it's no coincidence that arxanas is also involved in jj's development!
- aniviacat 1y agoIt's also quickly followed by: > Jujutsu is relatively new and doesn't cover 100% of the features of Git yet. So it's more powerful except when it's not.
- mamcx 1y agoOther do a lot of nitpicking in workflows (with responses that are expected, like "but who cares" or "in git I could do the same"), but not answer this: JJ is MORE powerful than git because has a BETTER SEMANTICS & ABSTRACTION. That its. Is like when git emerge, it was more powerful than svn because was distributed. I wanna make the point clear: Is NOT about the "amount of features or specific workflows" that with pain can be made on git and with effort could be retrofitted on jj eventually (if today are missed, like a equivalent of GitHub!). The power is what abstraction made jj that is different to git: We work on "commits" all the time, and not need to manually sync the state. Everything derive from this. And because is a better abstraction, it make more sense and is easier to understand. The UX derive from this.
- jennyholzer 1y agoI've seen some posts about Jujutsu recently, but I haven't gone deep into specific workflows. Are there specific advantages to using Jujutsu over Emacs Magit? All other Git UIs I've used have been severely lacking, but Magit has made me significantly more productive with Git, and has convinced me of the "magic of git". Is Jujutsu interested in competing with this experience? Or is it intended as an alternative to the (to be clear, extremely poor) git user experiences outside of Emacs?
- paradox460 1y agoJujutsu isn't really a git UI, and in some ways it's rather bad at being one (no support for making tags, submodules, or a few other things) It's a whole new VCS, that just so happens to be backwards compatible with git, and uses git as it's backend Similar to how git brought us cheap branching over svn, JJ brings cheap rebasing. Conflicts are no longer stop the world operations, and you can rebase, rearrange, and manage commits like never before. If you've used tools like stacked diffs before, JJ will feel right at home. Making stacked diff PRs is almost trivial in jj
- jennyholzer 1y agoStacked diffs is a great feature. Thanks for the response!
- paradox460 1y agoNo worries. JJ tends to fit modern software engineering a bit better than git, I've found. Here's sort of an example of what I do when I'm working with it I'll open an empty change on top of the main branch, not really sure about where this feature is going to go but knowing that it needs to be new changes. Usually this is already done for me automatically because my main synced with the remote, and therefore is an immutable commit. As I'm writing code I'm not really concerned with how I'm going to commit it to the graph, it's just a big pile of things all changing at the same time. Maybe I do features that are unrelated, or only tangentially related, to the actual story I'm working on. If I get interrupted, I might go over to JJ and describe my changes, typically something along the lines of work in progress with a list of what still needs to be done and what I've been trying to do, basically a capture of my state of mind at the time. I'll then create a new change on top of that, for when I can come back later. Once I'm finished with all of the story and it's working to my satisfaction, I probably have a big ball of changes that need to be split up and organized properly. First thing I do is look at what changes are necessary for this story, which are dependence for it, and which are just things I did because it was convenient to do them at the time. I'll split the dependencies out first putting them into their own changes. Then I'll make the actual story related changes, and then I'll make the ones that are just one offs. With a little bit of rebasing, I now will typically have three or four different bookmarks, which is the JJ analog of branches, some in parallel and some dependent on each other, that I can push up to my remote repository and open up pull requests. I made a couple shell scripts to handle some common things, like recursively splitting a change into parts, but you don't really need them, as they're just wrappers around built in JJ stuff or adaptations to some of my workflows. I touch on them in a blog post that's mostly about JJ: https://pdx.su/blog/2025-08-13-the-quiet-software-tooling-renaissance/ https://pdx.su/blog/2025-08-13-the-quiet-software-tooling-re...
- paradox460 1y agoI've been enjoying JJ recently, after giving it another try. I'd tried it when it was new, and the sharp corners were still a bit too sharp for my liking. JJ seems to be part of a new "era" of tooling that's just really good. I mused about this a bit in a blog post: https://pdx.su/blog/2025-08-13-the-quiet-software-tooling-renaissance/ https://pdx.su/blog/2025-08-13-the-quiet-software-tooling-re...
- nchmy 1y agoim glad to see you also use and love mise. Mise, jj (and its phenomenal jjui TUI, which I see you mentioned there), and uv for python are nothing short of revolutionary, as far as I'm concerned. Just beautiful tools.
- paradox460 1y agoI probably should mention things like atuin and fish, which bring, if not joy, absence of frustration when using my computer
- nchmy 1y agoAtuin is great too! I recently switched to it from fzf. zoxide is similar and beautiful as well. I use both all day.
- paradox460 1y agoI love zoxoxe, and even have it plugged into my Alfred, with minor tweaks
- stavros 1y agoI never managed to get into mise. I tried, but I think its documentation wasn't good enough for me to be able to configure the things I wanted, and, with uv, I barely ever see a need to use it... Does anyone have a use case where they use mise with Python? What do you use it for?
- ivanjermakov 1y ago> Jujutsu is easier to learn than Git. Git is known for its complicated, unintuitive user interface. Jujutsu gives you all the functionality of Git with a lot less complexity. Being easier to use does not mean being easier to learn. Complicated workflows requiring deep understanding might be harder to learn because of a higher abstraction.
- Disposal8433 1y ago> deep understanding It took me less than one day to switch from git.
- sfink 1y ago> Complicated workflows requiring deep understanding might be harder to learn because of a higher abstraction. That's a fair complaint, and where other git porcelains have failed in the past. I think the trick is that jj isn't raising the level of abstraction. Well, maybe in one place: there are change IDs in addition to commit IDs, and most of the time you'll want to be working with the change IDs. But even then, you could just use commit IDs, you'd just need to be looking them up all the time. jj adds on a minimum of new functionality. It just turns out that if you make the already-existing git graph the object of your CLI commands, you can actually expose all of the operations you need with a much smaller set of primitives, even those for constructing your complicated workflows. git has accreted commands and flags to handle everything you need because it restricts its focus to a single commit or ref. Sometimes a command will use that commit to imply a whole branch, sometimes not. It avoids mutating things because that'd make you lose track of the holy commit, but then it has to provide lots of tools for when you want to mutate things. It has a staging area so that you can delay creating a commit until it's stable enough -- but now you have another concept. Stashes are similar. (This actually undersells jj a bit. The op log and deferrable conflicts, for example, are bizarrely useful in practice even though they aren't fundamentally "needed". Nor do they raise the abstraction level. But going into that would dilute the message.)
- quectophoton 1y agoWould it be accurate to describe Jujutsu as "a Mercurial-inspired frontend for Git"? Also, another question I have for people who have used Jujutsu: Is it focused on interactive use, or is it also convenient to use for automatic/non-interactive use? For example, situations like: * A CI/CD pipeline that periodically adds stuff to the repo, or a pipeline that modifies files when triggered by specific events. * Server setup scripts that clone a repo with common config and then make a new commit after applying patches for host-specific changes.
- paradox460 1y agoNot really, but it's a strong enough description that people who know what both are would understand JJ is a whole new VCS, that just so happens to be backwards compatible with git, and currently uses git as it's storage engine It builds atop the knowledge we gained since mercurial and git were both new, not making mistakes that the others made, as well as knowledge from newer VCS systems like fig and sapling
- Rebelgecko 1y agoIMO its inspired by the best parts of git, hg, and darcs. jj split alone is worth the price of admission IMO I haven't done a TON of scripted use of jj, but when I have the built in templating has come in clutch. If you want a command to return in a certain format (or include/exclude certain metadata) it's usually easier- and probably more future proof- to tweak the jj command's template than to parse the string in your script.
- sfink 1y ago> Would it be accurate to describe Jujutsu as "a Mercurial-inspired frontend for Git"? In my opinion: yes. (Maybe with a slight caveat that I think some of the Mercurial inspiration came through Sapling.) And it's not limited to Mercurial/Sapling ideas, it has some new stuff too, but I think that still counts as "Mercurial-inspired". > Also, another question I have for people who have used Jujutsu: Is it focused on interactive use, or is it also convenient to use for automatic/non-interactive use? I use it in automation. I'm hampered because the primary VCS for the automation is git, so I'm doing more of a compatible layer and can't go too crazy with the jj-specific stuff. But jj has some features that are excellent for automation. Example: you can manually wrap things in a discardable transaction: grab the current operation ID, do all kinds of weird mutating operations that add and remove patches, maybe even merge and rebase, and then at the end (maybe in a `finally` block) do `jj operation restore <id>` and everything will go back to the way it was. Another example is that if you want to tweak something, say a config file, in N different ways, you don't have to mess around with naming branches and switching between them or whatever. Just create N independent child commits and make the appropriate changes in each. Or conversely: make M children for the M values of configuration value 1 and N children for the N values of configuration value 2, then create a new multiparented child (a merge commit) for each combination. `jj new <a> <b>` creates a merge commit with parents <a> and <b>, so: jj new $base -m 'var1=a' jj new $base -m 'var1=b' jj new $base -m 'var2=x' jj new $base -m 'var2=y' jj new 'description("var1=a")' 'description("var2=x")' -m 'var1=a, var2=x' # run scenario 1 with those settings jj new 'description("var1=a")' 'description("var2=y")' -m 'var1=a, var2=y' # run scenario 2 with those settings Sorry, I'm using the `description(...message...)` revset expression to retrieve the appropriate commits when in practice you'd probably record the IDs and do `jj new $a $x` with no descriptions anywhere. But hey, the above would work as written!
- firtstea 1y ago[flagged]
- thewisenerd 1y agoi've been using jj for the past few weeks on a feature heavy project. my entire "workflow" is no more than these 4 commands, rinse and repeat: jj new main@github jj describe jj git push -c {prefix} jj git fetch my couple thoughts: - i'm forced to be "strict" with my changeset since there's no `git add -P` - bookmarks are a pain to keep up-to-date with `jj new`, i don't know if i even want to do that. for multi-commit changes, i've defaulted to `jj new` a couple times as needed, and `git push -c` the latest. - i'm sure some day i'll understand the `@..` and `roots()` incantations but for now the most complex thing i've successfully pulled off is `jj rebase -s 'roots(main@github..@)' -d main@github` i don't think trying to map your current git flows 1-to-1 onto jj is going to be a very fruitful exercise.
- senekor 1y agoJust a few tips: > - i'm forced to be "strict" with my changeset since there's no `git add -P` Check out the command `jj split` and possibly `jj squash --interactive`. > - bookmarks are a pain to keep up-to-date with `jj new` There's a neat alias a lot of people use: ```toml [aliases] tug = ["bookmark", "move", "--from", "heads(::@- & bookmarks())", "--to", "@-"] ``` It finds the closest bookmark and moves it to `@-`. Pretty much exactly what you want when adding more commits on top of an existing branch.
- paradox460 1y ago> - i'm forced to be "strict" with my changeset since there's no `git add -P` JJ split is your friend > - bookmarks are a pain to keep up-to-date with `jj new`, i don't know if i even want to do that. for multi-commit changes, i've defaulted to `jj new` a couple times as needed, and `git push -c` the latest. Check out the common community alias JJ tug. It's used enough they're considering adding it as a feature
- epolanski 1y agoCan't you just add an alias that takes two arguments that takes a message and a bookmark name? I aliased the entire describe, commit, bookmark and push to a single command.
- 0-R-1-0-N 1y agoI would like to see an example of someone showing the workflow for using jj and doing feature branch. I don’t really get that yet. Most examples only show that they commit once and then push. But what if it requires multiple commits.
- hellcow 1y agoHere: $ jj new -m 'build my feature' $ touch my_feature.c $ jj new -m 'add some other feature' $ touch other_feature.c $ jj bookmark move main -t @ $ jj git push
- SAI_Peregrinus 1y agoOne way (there are other ways to do some things): `jj log` if needed to see what revision ID you need to use `jj new <starting revision> -m <message>` to create a new change with a given message with <starting revision> as the parent. (you can also use the `--insert-before <revset>` and/or `--insert-after <revset>` to set the parent & child revison(s) for the new revision). `jj bookmark set <feature 1 name> --revision <revset>` to make a bookmark (a branch name) on the revison you just made. Make changes on this branch as desired. `jj new` for each new change you want to have its own revision. If you added more revisions to the branch, `jj bookmark move <feature 1 name> --to '@'` (you can also use the change ID instead of '@', '@' just means "the current change you're editing"). `jj edit <starting revset>` to go back to your starting revset. `jj new -m <message>` to make a new revset on top of the starting revset (the starting revset now has two children: it has branched) `jj bookmark set <feature 2 name> --revision <revset>` to name the second branch you just created. Make changes as desired. `jj new` for each new change you want to have its own revision. If you added more revisions to the branch, `jj bookmark move <feature 2 name> --to '@'`. `jj new <feature 1 name> <feature 2 name> -m "merge feature 1 & feature 2"` to make a new revision with the feature 1 & feature 2 bookmark revisions as its parents (this is a merge). Alternatively, you could use `jj rebase` to move any number of commits to anywhere in the commit graph you want.
- njaremko 1y agoHas anyone who's enjoying Jujutsu tried Meta's Sapling? I've been using it lately with the VS Code plugin, and it's been great. My understanding is that Jujutsu is pretty heavily inspired by Sapling and Google's patch-based git workflow? https://sapling-scm.com/ https://sapling-scm.com/
- sunshowers 1y agoI used to work on Sapling and Mercurial while at Facebook. I've been using Jujutsu full time for the last two years. Jujutsu is in a sense the final form of that style of VCS, which I characterize as making commits first-class rather than branches, and providing powerful tools for managing long queues of stacked changes (git rebase -i is nice but has many limitations that don't exist in Jujutsu). I go into some more detail in my testimonial, the first one at https://jj-vcs.github.io/jj/latest/testimonials/#what-the-users-have-to-say https://jj-vcs.github.io/jj/latest/testimonials/#what-the-us....
- thramp 1y agoI’d second Rain’s reply, but having gone from git to sapling to jujutsu, I feel like the jump from sapling to jujutsu was as big as the jump from git to sapling, in terms of “oh, this is a way nicer workflow”. I really like and miss Sapling’s interactive smart log, but I found jj’s conceptual simplicity to be more compelling than ISL. That said, VisualJJ and Jujutsu Kaizen (both listed on https://jj-vcs.github.io/jj/latest/community_tools/ https://jj-vcs.github.io/jj/latest/community_tools/) might give you the ISL-style experience you’re looking for.
- sfink 1y agoI'm mostly git -> mercurial -> sapling -> jj. For me, Mercurial -> Sapling was a mostly lateral, slightly upward move. Sapling -> jj felt really good, though oddly not because anything felt horribly wrong or missing in Sapling. Things just feel nicer and lighter in jj. Once I know a couple of things, I can combine them to do lots and lots of other things without learning any new commands. In fact, the total command set is pretty small, yet covers about the same range as other systems (a little more here, a little less there). Also, improvements come in at understandable and predictable places: at its current stage of development, it's not growing brand new commands. It is instead slightly improving existing commands to enable significant new capabilities. It has the feel of a well-designed system with mostly orthogonal components. (Give it a decade, and perhaps it'll start crumbling under its own weight too...)
- layer8 1y agoOne showstopper for me is that Jujutsu doesn’t support .gitattributes (https://jj-vcs.github.io/jj/latest/git-compatibility/ https://jj-vcs.github.io/jj/latest/git-compatibility/).
- verdverm 1y agoor LFS, hooks, submodules, shallow clones
- odie5533 1y agoSo it doesn't have most of the worst features git ever invented. Got it.
- Cthulhu_ 1y agoI can understand the criticism to submodules but the rest of your comment feels like unwarranted snark.
- odie5533 1y agoHooks, submodules, and LFS all have huge followings of haters. I think just a week ago there was a big post on HN about how awful LFS is.
- SAI_Peregrinus 1y agoLFS is pretty crap, but the problem it tries to solve is real: version control should be able to control all the sources of the application, not just the text-based sources. Even if it can't meaningfully "diff" between them.
- wolvesechoes 1y ago[flagged]
- 1y ago
- Ericson2314 1y agoI want to read "Jutustsu for Git experts" For example, will the committing of conflicts (a good idea I agree), mess up my existing git rerere? Also I agree that the staged vs unstaged distinction is stupid and should be abolished, but I do like intentionally staging "the parts of the patch I like" while I work with git add -p. Is there a a lightweight way to have such a 2-patch-deep patch set with JJ that won't involve touching timestamps unnecessarily, causing extra rebuilds with stupid build systems?
- mdaniel 1y ago> Also I agree that the staged vs unstaged distinction is stupid ... > I do like intentionally staging "the parts of the patch I like" while I work with git add -p is a mysterious perspective to me. I guess with enough $(git worktree && git diff && vi && git apply) it'd be possible to achieve the staging behavior without formally staging anything but yikes I just checked and it seems that mercurial 7.1 still doesn't believe in $(hg add -p) so presumably that 'worktree' silliness is the only way to interactively add work in their world
- sunshowers 1y agoIn Mercurial you'd do hg commit -i and squash further changes down incrementally via hg amend -i, similar to Jujutsu. (The first thing about Jujutsu that was earth-shattering for me was learning that jj amend is an alias for jj squash. I swore aloud for several minutes when I first learned that.)
- mdaniel 1y agoHow would anyone possibly know that? https://mercurial-scm.org/help/commands/commit https://mercurial-scm.org/help/commands/commit says no such thing but I also recognize that I am obviously a fool for thinking that one should add the whole file but only commit part of it I guess that also places the burden upon the user to .. I dunno, go through that whole TUI dance again?, if one wishes to amend one more line in the file In some sense, I do recognize it's like showing up to an emacs meeting and bitching about how it doesn't do things the vim way, but seriously, who came up with that mental model for committing only part of the working directory?
- collinmcnulty 1y agoI’ll hop on the train and say that I’ve been using jj recently as well, and it’s given me that feeling of safety and freedom I got when I first started using version control 10 years ago. That sense that “well this is a crazy idea but I’ll just commit now and try it, I can always roll back”.
- KingMob 1y agoIt's still insane to me that universal `undo` is not a basic git command.
- Cthulhu_ 1y agoThat's because there is none, because you're dealing with 4 locations (local, staging, local branch, remote branch); which one do you want to undo?
- KingMob 1y agoAny of them. All of them. (Maybe not remote changes, but that's way less safe to attempt, even if possible.) Which is what `jj undo` does, and why I brought it up. I'm well aware git doesn't have a unified concept of undoing, but I'm equally aware that it's possible. (Even before jj, GitUp and git-branchless offered universal undo.)
- SAI_Peregrinus 1y agoNot to mention Git has a reflog, so `undo` could just always revert the last operation in the reflog. Or the last `n` operations if specified. So there already is a universal list of what operations were performed, and thus what operations for `undo` to work on.
- phatskat 1y agoGit always baffled me with revert - I learned early on that if I wanted to “undo” something, the best bet was to either branch from a commit before the thing I want undone, and maybe rebase/cherry pick later commits, or just start over. This seems like the ideal case for revert, but the way that it alters the history stings - the fact that reverting a commit essentially means that said commit can’t show up later as a change is frustrating - also I’m sure it’s a case of user error, but…”merge branch, realize there’s a big oops in there, revert, fix the oops on the branch” feels like it shouldn’t result in a state where git doesn’t accept the branch as mergable.
- alabhyajindal 1y agoI don't know anything about Jujutsu but the Git equivalents for some of these commands are more readable: jj bookmark move main --to @- git add . jj git init --colocate git init Also using `jj git` everytime feels repetitive.
- a022311 1y agoThis feels like a troll, but I'll answer anyway. The first command you mention is `jj bookmark move main --to @-`, which apart from the `@-` part, is easily read and does exactly what is written. It moves the main bookmark to the parent commit. The main difference to git here is that updating a branch is an explicit action. Jujutsu supports creating aliases and many users have a `jj tug` alias that moves the current closest branch to point to the parent commit. `git add .` just adds all changed files in the current directory to the current commit. That's an entirely different thing and Jujutsu takes care of doing that automatically. The second command creates a git repository and while it is longer, I doubt the extra keystrokes will hurt you much. If it's too long, just alias it. As for using `jj git`, since Jujutsu supports multiple backends, backend-specific commands require the `git` namespace. You generally only need it for cloning, pushing and fetching (with the option for aliases again). You'll rarely need to create a new repository or add a remote.
- alabhyajindal 1y agoThanks for your reply! I wasn't trying to be dismissive in my original comment. Just making an observation as someone new to Jujutsu.
- a022311 1y agoIn that case, I apologize for treating your comment that way. Written text can make communicating intent so hard...
- zamalek 1y agoI'm a through-and-through JJ convert. One papercut I have experienced a few times (though I am getting much better at avoiding) is what to do when I forget to `jj new`. Assuming that I have pushed the current bookmark to the remote, is there any way to recover a new change that is the diff against the remote? I have tried rebasing, but that leads to bookmark ambiguity instead of the solution I'm looking for.
- AndrewHampton 1y agoIs `jj split` a good option?
- zamalek 1y agoI've tried it, but then I have to remember what has been pushed.
- dylanhu 1y agoI also run into this often, I wonder if there is a simple built-in feature that would allow you to diff against the remote.
- paradox460 1y agoInterdiff
- abound 1y agoThere's a few different ways to fix this, but here's what the official docs suggest: https://jj-vcs.github.io/jj/latest/FAQ/#i-accidentally-changed-files-in-the-wrong-commit-how-do-i-move-the-recent-changes-into-another-commit https://jj-vcs.github.io/jj/latest/FAQ/#i-accidentally-chang... TL;DR - `jj evolog` and then restore changes from the relevant secret commit ID
- zamalek 1y agoBut that would undo what I've done, right? I Wang to keep the changes but only diff them against what I've pushed.
- BeetleB 1y agoI had used jj for only a month before I switched back to git for a particular project at work. I felt that jj was *really* nice, but nothing more. After returning to vanilla git, I was missing the jj convenience within hours. https://blog.nawaz.org/posts/2025/Aug/the-jujutsu-effect/ https://blog.nawaz.org/posts/2025/Aug/the-jujutsu-effect/
- incognito124 1y agoSomething about appreciating only after losing
- ysofunny 1y agoalso, demonstrating a marked improvement in the experience. it really does seem like we all gonna be using jj soon enough I recall pijul.org that was another working prototype of better git and I wonder how much overlap is there in the way they have made the improvements.
- fiddlerwoaroof 1y agopijul uses a completely different model of version control than git (stores diffs rather than snapshots). And so the cost of switching and interoperation is a bit higher than jj which basically acts like a nice UI over git.
- ivanb 1y agoSupposedly, Pijul doesn't have the "force-push to trunk" problem. This alone makes it interesting.
- baq 1y agopijul is one of the projects that I’d just sponsor a team for a few years if I was a megacorp or a government research agency because it’s just so damn cool in theory, but has too many rough edges in day to day practice (IOW I’d like to try it but would need pijul colocate for it to make sense)
- hooper 1y ago
- notallm 1y agothought i was gonna learn how to fight for a second lol
- efilife 1y agosame, I'm kinda disappointed
- palata 1y ago> Jujutsu is more powerful than Git Depends on your workflow, I guess. I need to sign with different security keys, and for that I use "defaultKeyCommand" in git. Doesn't exist in Jujutsu.
- mdaniel 1y agoI was one of the early adopters (cause I enjoy kicking the tires on things) and brought awareness of the need for gpg signing at all into JJ, so I wouldn't overlook the value in bumping https://github.com/jj-vcs/jj/issues/6688 https://github.com/jj-vcs/jj/issues/6688 so they can eventually get you there
- palata 1y agoTo be honest, the more I use jj, the more it feels like it's not yet mature enough for me. It doesn't support git push options, for instance. I have already found more things that I cannot do with jj (and can do with git) than things that are nicer to do in jj. Though admittedly, there are things in jj that are better. Hopefully it will get there eventually :-). But these things take time. JJ already seems to get a lot of attention, so that's something.
- xmonkee 1y agoDoes jj effectively support stacked diffs on github? I've been paying through the nose for Graphite lately because it does, and the feeling I get is I'm just paying for their nice cli tool. `gt create` and `gt sync` is all I need. I don't really fully agree that their interface is entirely necessary or worth the $3500 per year it costs right now for my team.
- baq 1y agoGitHub needs to redesign PRs to properly support stacking them. It isn’t a client problem, but jj does make rebasing multiple branches correctly trivial, so if GitHub supported this workflow in a non-pretend fashion, it’d work. If rebasing correctly is enough to support your use case, then the answer is ‘it’ll work’.
- shepherdjerred 1y agojj is great, but it doesn't quite fill the void of Graphite. I've heard good things about https://abhinav.github.io/git-spice/ https://abhinav.github.io/git-spice/
- seivan 1y ago[dead]
- paradox460 1y agoKind of. You can do most of it by hand, and there are some community made tools that improve the experience and basically give you graphite lite https://github.com/keanemind/jj-stack https://github.com/keanemind/jj-stack
- KingMob 1y agoNo, sadly, that's more of a Github limitation.
- cube2222 1y agoJujutsu is pretty excellent. I’ve tried it a couple months back (and written about, along with a couple common patterns [0]) and have been using it since. It’s just a very “consistent” experience. I never really had issues with git (so didn’t expect I’d stay with jj), but for anything more advanced I’d generally have to google. In jj everything is based on a couple primitives, and it’s easy to combine them to do history reshaping of arbitrary complexity. My workflow used to be very stash-oriented, and with the way jj changes work, auto tracking, and letting me switch between changes, it ends up being much more pleasant than git. Rebasing with conflict resolution is generally much nicer too (esp. in the stash-like workflow). Anyway, very recommended, and effort required to switch is very small. [0]: https://kubamartin.com/posts/introduction-to-the-jujutsu-vcs/ https://kubamartin.com/posts/introduction-to-the-jujutsu-vcs...
- lvl155 1y agoOT, but are there agent-specific versioning systems? Or are people just retrofitting git/jj?
- KolmogorovComp 1y agoWhy would agents need a specific versioning system?
- jdmg94 1y agowhat does "retrofitting" git implies? I am confused by the agent-specific systems bit.
- ivanb 1y agoI haven't yet given jj a proper trial, so pardon the ignorance. All I've seen are conveniences regarding the working the copy. Besides the subjectively terrible UI, my biggest gripes with Git have to do with collaboration. A rebase may unintentionally overwrite someone's work. A force-push to trunk breaks every other developer's working copy. With "distributed" being in the name of this whole class of VCSes, I would expect that such things just wouldn't happen, but here we are. As I understand it, jj inherits all of these problems and adds better concepts and UI for manipulating the working copy. I'm not sure this alone is a good enough justification for a switch. Of all the Git's features I use a tiny, proven subset and stay on the beaten path. It makes it bearable enough.
- dzaima 1y agoWorking copy handling differences is certainly an aspect of jj, but, at least for me personally (esp. given me having grown up with git), it's probably my least favorite difference from git. And yet I've moved most of my personal things from git to jj (albeit with a bunch of custom scripts to make the working copy stuff more git-y). A significant other thing jj does is introduce change IDs (i.e. a (randomly-generated) ID that stays stable even as a commit is amended), with which it should be easier to track changed commits across forks/rebases/edits/pulls/fetches, though I've yet to use jj for collaborative projects to see how much that pans out. Generally jj makes rebasing things, and generally editing history so much more easy than git, so force-pushes messing with branches is much nicer to "fix" however needed. Being able to leave commits in a conflicted state and resolving only when actually needed also should help.
- paradox460 1y agoOne of the quiet bit of genius is that JJ change ids use a different set of characters for base16. Instead of 0-9A-F they use k-z
- sfink 1y agoTechnically, it's z-k (z=0, k=15). It makes for a nice root change ID: zzzzzzzz. Less choking than kkkkkkkk. The relevance, btw, is that you can use git commit IDs in place of change IDs anywhere and they won't conflict; jj knows which you mean by the character set. (They could still conflict with bookmark names, sadly. But I haven't heard of that being an issue in practice.)
- IshKebab 1y agoAnother question for jj people: one concrete thing I find annoying with Git is that it's completely incapable or rebasing anything with merge commits. Can jj do this? Even very simple merges are too much for git to rebase. It's especially annoying with `git subtree`. If I want to rebase anything to do with that I don't bother now - I just start again from scratch.
- aseipp 1y agoYes. I have one repository, which is a fork of an OSS project, with a 7-way octopus merge of various patches I carry, and another 2-way merge on top of that one. Every week or two I pull the latest changes from upstream and I rebase all 9+ branches in a single command. If there are conflicts on any one of the parallel streams of work, I can trivially fix each conflict individually in any order I want. Jujutsu does not treat merge commits any more or less special than non-merge "1-parent" commits. (We used to do this, actually, and occasionally special case merges, but most users found it very confusing.) This regularity means most commands work fine on merges. 'jj new X' is a new commit on top of X. 'jj new X Y' is a merge commit with X and Y as parents. 'jj new X Y Z...' is a 3-way merge, and so on and so forth for any number of commits. Similarly, 'jj rebase' can handle moving commits and preserving the graph structure no matter how many edges are involved in particular, and can add or remove parents from a given commit. This means that conceptually the jj commit graph is merely a simple, ordinary DAG, and operations are transformations on the DAG like you expect. Actually, this exact workflow is beloved by many community members, and I guess I can take responsibility for popularizing it originally, the "Mega Merge" technique. Instant, easy rebase is an essential part of making this technique viable. - https://ofcr.se/jujutsu-merge-workflow https://ofcr.se/jujutsu-merge-workflow - https://v5.chriskrycho.com/journal/jujutsu-megamerges-and-jj-absorb/ https://v5.chriskrycho.com/journal/jujutsu-megamerges-and-jj...
- Human-Cabbage 1y agoTo reinforce the sibling reply with a concrete example: Let's say you've got a few feature branches, all based of the trunk branch. $ jj @ ozywpwxm samfredrickson@gmail.com 2025-08-31 13:21:59 b2f1364d │ (empty) (no description set) │ ○ qxoklwxv samfredrickson@gmail.com 2025-08-31 13:21:27 9cda0936 ├─╯ (empty) Feature C │ ○ ukqynvts samfredrickson@gmail.com 2025-08-31 13:21:26 ceee7029 ├─╯ (empty) Feature B │ ○ nwtxnvxp samfredrickson@gmail.com 2025-08-31 13:21:24 9ccbedf6 ├─╯ (empty) Feature A ◆ yxuvtolz samfredrickson@gmail.com 2025-08-27 09:49:16 master git_head() 8e80b150 │ Update Claude Code to 1.0.93. One neat workflow supported by Jujutsu is "working on all branches at the same time." $ jj new q u n Working copy (@) now at: zzxxqlzr fb73d4dc (empty) (no description set) Parent commit (@-) : qxoklwxv 9cda0936 (empty) Feature C Parent commit (@-) : ukqynvts ceee7029 (empty) Feature B Parent commit (@-) : nwtxnvxp 9ccbedf6 (empty) Feature A $ jj @ rzouzmyw samfredrickson@gmail.com 2025-08-31 13:25:56 fb73d4dc ├─┬─╮ (empty) (no description set) │ │ ○ nwtxnvxp samfredrickson@gmail.com 2025-08-31 13:21:24 9ccbedf6 │ │ │ (empty) Feature A │ ○ │ ukqynvts samfredrickson@gmail.com 2025-08-31 13:21:26 ceee7029 │ ├─╯ (empty) Feature B ○ │ qxoklwxv samfredrickson@gmail.com 2025-08-31 13:21:27 git_head() 9cda0936 ├─╯ (empty) Feature C ◆ yxuvtolz samfredrickson@gmail.com 2025-08-27 09:49:16 master 8e80b150 │ Update Claude Code to 1.0.93. ~ Now you can use the merge revision as a scratch space, and then squash changes from it into one of the feature revisions. $ vim README.md $ jj squash --into n Working copy (@) now at: rzouzmyw 30ff9b0f (empty) (no description set) Parent commit (@-) : qxoklwxv 9cda0936 (empty) Feature C Parent commit (@-) : ukqynvts ceee7029 (empty) Feature B Parent commit (@-) : nwtxnvxp fb3cca28 Feature A $ jj @ rzouzmyw samfredrickson@gmail.com 2025-08-31 13:27:41 30ff9b0f ├─┬─╮ (empty) (no description set) │ │ ○ nwtxnvxp samfredrickson@gmail.com 2025-08-31 13:27:41 fb3cca28 │ │ │ Feature A │ ○ │ ukqynvts samfredrickson@gmail.com 2025-08-31 13:21:26 ceee7029 │ ├─╯ (empty) Feature B ○ │ qxoklwxv samfredrickson@gmail.com 2025-08-31 13:21:27 git_head() 9cda0936 ├─╯ (empty) Feature C ◆ yxuvtolz samfredrickson@gmail.com 2025-08-27 09:49:16 master 8e80b150 │ Update Claude Code to 1.0.93. Later, you decide to fetch changes from your remote, and notice that your revisions are based on an out-of-date version of the trunk. $ jj git fetch remote: Enumerating objects: 17, done. remote: Total 12 (delta 6), reused 0 (delta 0), pack-reused 0 bookmark: master@origin [updated] tracked $ jj @ rzouzmyw samfredrickson@gmail.com 2025-08-31 13:27:41 30ff9b0f ├─┬─╮ (empty) (no description set) │ │ ○ nwtxnvxp samfredrickson@gmail.com 2025-08-31 13:27:41 fb3cca28 │ │ │ Feature A │ ○ │ ukqynvts samfredrickson@gmail.com 2025-08-31 13:21:26 ceee7029 │ ├─╯ (empty) Feature B ○ │ qxoklwxv samfredrickson@gmail.com 2025-08-31 13:21:27 git_head() 9cda0936 ├─╯ (empty) Feature C │ ◆ zvpmmzru samfredrickson@gmail.com 2025-08-29 15:59:55 master 658a3d12 │ │ Update Claude Code to 1.0.98. │ ~ (elided revisions) ├─╯ ◆ yxuvtolz samfredrickson@gmail.com 2025-08-27 09:49:16 8e80b150 │ Update Claude Code to 1.0.93. ~ With Jujutsu, you can run one command to rebase _everything_ against the latest trunk revision. $ jj rebase -s 'roots(trunk()..mutable())' -d 'trunk()' Rebased 4 commits to destination Working copy (@) now at: rzouzmyw 88ed8085 (empty) (no description set) Parent commit (@-) : qxoklwxv 005442c3 (empty) Feature C Parent commit (@-) : ukqynvts 23923cf2 (empty) Feature B Parent commit (@-) : nwtxnvxp 769d0539 Feature A Added 0 files, modified 2 files, removed 0 files $ jj @ rzouzmyw samfredrickson@gmail.com 2025-08-31 13:32:08 88ed8085 ├─┬─╮ (empty) (no description set) │ │ ○ nwtxnvxp samfredrickson@gmail.com 2025-08-31 13:32:08 769d0539 │ │ │ Feature A │ ○ │ ukqynvts samfredrickson@gmail.com 2025-08-31 13:32:08 23923cf2 │ ├─╯ (empty) Feature B ○ │ qxoklwxv samfredrickson@gmail.com 2025-08-31 13:32:08 git_head() 005442c3 ├─╯ (empty) Feature C ◆ zvpmmzru samfredrickson@gmail.com 2025-08-29 15:59:55 master 658a3d12 │ Update Claude Code to 1.0.98. ~ I use this command so much that it's aliased as "jjsr", "Jujutsu Super Rebase".
- a022311 1y agoNice work! I've been using Jujutsu for almost 5 months and have completely replaced git. In fact, I've interacted with Git only 52 times (41 if we exclude my invocations of `--help` xD) since then vs 582 with Jujutsu. Instead of having to adapt to a particular workflow, Jujutsu is flexible enough to support pretty much any workflow. Even when mostly using it like git, I have the freedom to jump around commits and branches (no stashing required), rebase easily (this may be simple for git power users, but I really appreciate being able to do this without VSCode's git tools) and just... get work done without extra headaches caused by VCS. And all that while writing my changes to an actual git repository just like everybody else's, that git tooling can interact with. When was the last time you used a different VCS than your coworkers without having them switch to it too? While there are some rough edges regarding tags, submodules and LFS (I might be missing something else here), it's certainly worth a try.
- wocram 1y agoWhat is the replacement for `git branch --set-upstream-to`?
- a022311 1y agoUnfortunately there is no replacement for it and I miss the feature too. The docs [1] mention: > Unlike in Git, the remote to push to is not derived from the tracked remote bookmarks. Use `--remote` to select the remote Git repository by name. There is no option to push to multiple remotes. I think this was an explicit design decision, which I'm guessing might be because bookmarks in other storage backends (non-git) may not have a notion of an upstream URL. I'm no expert on this, you'll probably get a better answer by asking the maintainers themselves. Currently the best you can probably do is creating an alias to push a branch to a specific remote to save you some keystrokes. I hope that helps! [1]: https://jj-vcs.github.io/jj/latest/cli-reference/#jj-git-push https://jj-vcs.github.io/jj/latest/cli-reference/#jj-git-pus...
- wocram 1y agoIn git remote branches have no notion of an upstream branch either, it's a fully local construct you end up responsible for annotating.
- amadeuspagel 1y ago> Jujutsu is compatible with Git. You're not actually losing anything by using Jujutsu. You can work with it on any existing project that uses Git for version control without issues. Tools that integrate with Git mostly work just as well with Jujutsu. If I use git from zed and jj from the command line, will that just work?
- paradox460 1y agoGenerally. JJ will sometimes leave git in a detached head state, but it's usually pretty easy to recover from on the git side. The one thing I'd caution on is making sure you keep your bookmarks on the JJ side up to date. These translate to branches, which git needs to know where it is You might want to set up this feature: https://github.com/jj-vcs/jj/discussions/3549 https://github.com/jj-vcs/jj/discussions/3549
- BeetleB 1y agoIf people want an example of jj being more powerful yet simpler than git: jj doesn't have an explicit concept of the staging area or the stash, but it supports both and in a more powerful way. In jj, the staging area is simply a terminal node in the graph. You make the changes you want. And when you are ready to commit, you simply push all the changes to the parent node. The terminal node is your index, the parent is the committed node. This is a construct that is entirely in your mind. You don't have to work this way, but if you really like the concept of a staging area, that's how you do it. Have you ever done a git add, then made some changes, done a subsequent git add, only to realize you clobbered some important code that was in your first git add? How are you going to recover from this? I don't know if the git reflog has this information. In jj, everything is saved. Think of each commit in jj as a supernode. Inside the supernode are a bunch of atomic nodes. You can think of each atomic node as the equivalent of doing a git add, with each git add being another atomic node in that supernode. So if you've ever clobbered your changes like this, you simply go and remove the last atomic node or modify it however you want to resolve it. Effectively, jj gives your index its own version control. Similarly, in jj, a stash is simply a branch. It's a node in a branch that stores the state of the working directory. If you're in the middle of a feature and suddenly need to stop working on it to work on something else, you simply make a new node off the relevant node you're going to work from. In other words, you will just create a new branch while retaining your work in its own branch. Have you ever popped from the stash, made some changes, and then realized you clobbered something really important and wished you'd applied the stash instead of popping it? That's not at all a concern in jj. Effectively, you have a version controlled stash, and you naturally stash in jj without ever having to know the concept of a stash. After I'd been using jj, having a separate concept called "index" and a separate concept called "stash" suddenly seemed ridiculous. I don't know why Git decided to have these distinct concepts. At the end of the day, it's all a graph and you are manipulating nodes and the contents within each node. What you need are operations to help you manipulate those. I have to really emphasize that a typical jj user gets all this power just by learning a few operations - they don't have to learn so many different concepts. How many different ways are there to do a git reset? In jj, I've only ever had to do jj undo and it covers pretty much all those use cases.
- ygouzerh 1y ago
- idoubtit 1y agoI've now seen a dozen of articles that explain that jj is wonderful and better than Git for everything. This tutorial is of the same kind. Now that I've read extensively about the good part, I'd be more interested by the bad and the ugly. Because my experience with jj was more balanced. When I tried jj, I found a few pain points that made me return to Git. For instance, I was sharing a branch with a co-worker where we were just piling commits as soon as they were ready (after `pull --rebase` if necessary). Since jj doesn't have names branches, that workflow was easy with git and tedious with jj – even with the `tug` alias. The process in the "Tracking remote bookmarks" chapter of this tutorial still doesn't look nice to me. Another pain point was that jj could not colocate with light clones, like `git clone --filter=blob:none`. Maybe that's fixed now.
- wocram 1y agohttps://github.com/jj-vcs/jj/discussions/3549 https://github.com/jj-vcs/jj/discussions/3549 exists to simplify the tug workflow somewhat.
- stouset 1y agoI’m slightly confused. jj has named branches. They’re just called “bookmarks”. Once you track the remote bookmark, `jj git fetch` will update your local one to match the remote.
- adito 1y agoYeah, I don't get GP either, maybe their setup is different and more complex?
- MrJohz 1y agoBookmarks are similar to branches (and I believe implemented as branches?) but aren't quite the same thing. In particular, you can't check out a bookmark, you can only check out commits. If you do something like `jj edit <bookmark>`, it'll resolve <bookmark> to figure out which commit it points to, and then check out that commit. If you create a new commit now, the bookmark won't automatically be moved along, because jj doesn't know if you want to add a new commit to the <bookmark> branch, or if you're trying to create a new branch that forks off <bookmark>. Whereas `git checkout <bookmark>` puts you in a state where you've checked out the _branch_ and not the commit, which means if you create more commits, they'll automatically be added to <bookmark>. To create a branch forking off from <bookmark>, you need to first create a new named branch, then start adding commits to it. (There are other ways as well, but this is the most standard approach.) The tradeoff with Jujutsu's approach is that it's very easy to create lots of lightweight spin-off branches (just `jj new <fork point>`, no need to come up with names first). But it's slightly harder to do the traditional linear approach where you're consistently committing in a straight line on a single branch, and then syncing that branch with another remote. This is because for each new commit you create, you also need to update the bookmark manually. In the parent poster's case, it's probably complicated further by them working on the same branch as someone else. Assuming there's no rebasing going on, this shouldn't be too complicated, but it's another case where in git you would check out a branch, and `git pull` will automatically forward you to the head of the branch, whereas `jj git fetch` will just move the bookmark without moving you. It sounds like the workflow that this person is using doesn't fit that well with how jj "wants" to be used. I believe there's been some talk in jj of a way to automatically update branches when creating a new commit, which would help somewhat, but I think it's also a natural effect of having built their workflow around git, and that flow just not quite working so well in jj.
- tombert 1y agoInteresting; despite being chronically online I hadn't actually heard of Jujutsu before. I like the idea of a better VCS still using Git under the covers, if for no other reason so that I can continue to use Github or Gitlab to back up and share my code with people. I've never been able to stick with Fossil or Bitkeeper even though they are both very neat because they've never been "sufficiently better" to override the network-effect of Git's popularity. I'll need to play with this. I don't know that I'll stick with it but I'd be happy enough to be wrong.
- ec109685 1y agoThis tutorial is excellent. It’d be helpful to also include how jj flows map to pull requests in the GitHub/GitLab model, since many new jj users collaborate via PRs with main protected by default. What’s the best way to represent a stack? How do you model jj’s editing a commit at the bottom where everything above implicitly rebases when pull requests are open? One of the most intimating things is fumbling around with your vcs when an expert is reviewing your code.
- raylu 1y agoI'm having a hard time understanding your question. are you asking how people who are unfamiliar with git and jj should mentally model a stack of PRs? and that this is a problem because it's intimidating for them when an expert (in git? in the codebase?) is reviewing their code? if yes: while jj does make stacked PRs quite easy, I think this tutorial is mostly aimed at people who are still getting their feet wet and not making stacks of PRs. and if the expert is intimidating, tell them to be helpful or fuck off if no: well I don't understand your question, but probably don't `jj edit` the commit at the bottom of a stack; `jj new` and, when you're ready, either `jj squash` it down or `jj rebase -s @ -A @-` your change into the stack instead
- seivan 1y ago[dead]
- SAI_Peregrinus 1y agoI'll use my case as an example (though I haven't tried this yet, maybe it'll be seamless): I'm working in a monorepo on GitHub, where PRs get squash-merged & `main` is a protected branch, and a bot automatically tags every team for review if a commit in a PR branch has changed any of their files (anything they're in an OWNERS file for), then how do I work with `jj` so as not to tag the entire company if I develop a long-running feature branch alongside several other devs on my team? We need to periodically merge in changes from `main` as the feature is developed, but don't want to merge the feature until it's ready for release. With `git`, any use of `rebase` to get changes from `main` into the feature branch causes the bot to tag every team that merged anything to `main` between the creation of the feature branch & the use of the `rebase`. I'm not on the team that controls the bot, and I don't care to try to get them to change it. I happily use `jj` for anything I can get away with it on, but `git rebase` + monorepo + PR-centric workflow = pain, and `jj` seems like it could cause the same sort of issues. I should just try with a dummy branch & see, but that takes time & I've been busy.
- thibran 1y agojj clicks almost for me. I still struggle to understand when do I switch to a "branch" using 'jj new' and when do I use 'jj edit'. Also the manual setting of bookmarks after 'jj git pull' seems strange.
- holyshitsss 1y agoGreat point about performance. I think the next step is figuring out how to make this accessible to smaller teams without the big tech resources.
- holyshitsss 1y ago[dead]
- sieabahlpark 1y ago[dead]
- cynicalsecurity 1y ago[flagged]
- sunshowers 1y ago> fame I think it's great when people become famous for building useful, high-quality works, and other pro-social activities! > money Jujutsu is free software in both senses of the word.
- cynicalsecurity 1y ago> Jujutsu is free software in both senses of the word. It is not free for me. I would need to spend my time on learning it if I would ever encounter it in the wild. The time I could otherwise spend on my family, projects or hobbies. While having no benefits over git, it's trying to steal my time and make my life more complicated, by trying to introduce just another code versioning system no one asked for.
- sunshowers 1y agoDo you use version control professionally? Part of professional life is continuing education.
- cynicalsecurity 1y agoYes, I'm using git and I'm quite happy with it. I don't need to learn someone's hobby project as a part of my professional life.
- hu3 1y agoPersonally I don't think adding a layer on top of git is a good idea. I know it's hard to break git's hegemony but it would be much more powerful and less constrained to build on top of a new foundation.
- dcre 1y agojj’s design is not constrained by git. git is one possible backend, but you don’t even need to use jj with git. I will eat a shoe if you can name something jj is prevented from doing by its relation to git.
- hu3 1y agoInteresting. How can I use jj without git?
- tfsh 1y agoRight now there's no active public backends, there are a few prolific JJ contributors who are working on their own forge though (https://ersc.io https://ersc.io). At Google, JJ is natively supported for interfacing with the monorepo, this is where the proof of being backend agnostic comes from. Hopefully as the network effects catches on we'll see more and more of a desire for 3P forges.
- KingMob 1y agoYou might be interested in pijul then, which has a theory of patches that is interesting.
- SAI_Peregrinus 1y agoGit is a content-addressable filesystem with a VCS interface on top of it. jj needs a content-addressable filesystem for a backend, and currently only uses git's implementation in released versions, but the devs are working on their own to serve as a "native" backend. At least in theory, just about any content-addressable filesystem could be used, e.g. IPFS, though many would not be efficient.
- stevage 1y agoIn case the author is reading, can I suggest reformatting this kind of thing: >The command jj log shows you a visual representation of your version history. If you run it, you should see something like this: > @ mkmqlnox alice@local 2025-07-22 20:15:56 f6feaadf To: > The command jj log shows you a visual representation of your version history. > $ jj log > @ mkmqlnox alice@local 2025-07-22 20:15:56 f6feaadf Much better for learning when the command itself is part included in the output.
- rich_sasha 1y agoHaving disliked Git for a long time, I concluded that looking for alternatives is actually a waste of time, unless you do it as a hobby. VCSes are natural monopolies. There is a natural and unforced benefit from using the same thing as everyone else, unless it is so terrible that you literally can't work it. Because: 1. You use it for collaboration with others 2. You use it on new or under-configured machines where suddenly you're stuck with the lowest common denominator, ie got 3. 99%+ of online materials assume you're using git. 4. The RoI is actually not that great. If you do learn the system, you're only in the same place professionally as if you learned git in the first place. Git is famous for its user interface, and not in a good way. But the 5-8 commands I use daily, I now remember. I still have to Google for interactive rebase or how to nuke last commit - but I do it rarely enough that it doesn't matter. Jujutsu sounds really nice, likewise I really wanted to like mercurial. But in the end I decided it wasn't worth my time.
- KingMob 1y agoThis over-estimates the lock-in, because jj uses git under the hood. You can try jj, and your colleagues need never know. If you hate it after a couple weeks, you can return to git, no sweat. It's much easier to try out than earlier VC systems.
- sltr 1y agoI can also recommend Koppel's JJ Workshop https://github.com/jkoppel/jj-workshop https://github.com/jkoppel/jj-workshop
- monster_truck 1y agoI'm not using a cli to manage my code, it's 2025. I want gittower and gitlab, I want shortcut keys and first class support in _everything_, I'm a professional. If anybody paying me ever says I have to use it, I'll be using git anyways just like I did with clearcase, svn, mercurial, etc etc A quick scan of this thread reveals no less than 4 show stopping missing features. By the way, where are submodules? I see sentences like "you can work on every branch at the same time" and think "wow this would be great if I really wanted to fuck something up, now show me how you'd track this down to unfuck it a few years later in an unfamiliar codebase. With a gui. For use as evidence in a criminal court case" Keep plugging away. If this is how you think you can make the world of software a better place, I'm cheering for you.
- steveklabnik 1y agoThere are many different guis you can use with jj. It’s true that submodules aren’t directly supported, but you can use the git commands to manage them hntil native support comes.
- yencabulator 1y agoOh, many? What's out there beyond GG? All I see is TUIs and VSCode plugins. (I really like gg's promise of drag-and-drop editing, but I'm keen to try alternatives.)
- steveklabnik 1y agoSorry, yeah, I meant “non CLI interfaces”, I’m not sure if there are other “pure GUI” or whatever you call “non TUI non CLI plugin graphical interfaces”.
- sfink 1y agoYou can have most of that stuff, but it doesn't sound like that would sway you anyway. (And those 4 missing features may truly be showstoppers for you, in which case you're absolutely correct to stick with git.) There are early adopters and late adopters, and both have good reasons for being the one they are. You do you.
- jaberjaber23 1y ago[flagged]
- DAddYE 1y agoHow does JJ works with LazyGit? I can’t see myself living without it.
- paradox460 1y agoReplaces it entirely Check out jjui. While it's not a 1:1 of lazygit, it's better in some ways and lacking in others, but quickly getting better. I really enjoy that it shows you the command every action runs under the hood. Great to expand your knowledge of JJ early on
- steveklabnik 1y agoThere is a lazyjj but I don’t use lazygit so I can’t comment on how complete of an alternative it is.
- sbinnee 1y agoI happened to listen to a podcast episode yesterday where the topic was Git rebase. There were 4 people in the panel. One person made a point that he did not understand why they even care, saying basically Git is broken, all the VCSs are broken because they are too complicated and they get in the way. He said a lot of things but my take was that all the existing VCSs are just a distraction. I personally don't agree with him. But while listening to his argument, I started imagining a perfect VCS which is not Git, JuJutsu, perforce, or whatever. This got me thinking why I have not tried Jujutsu yet (which was mentioned in the episode briefly) even after I saw it multiple times on HN over the years. It is probably because it just looks like another Git, maybe a less complicated one. But nonetheless it's going to be Git-like, and I know enough about Git and am competent with it. So there is little incentive to learn and try another Git-like tool. I would love to try a VCS vastly different from Git. But it cannot be just different, it should be better than Git. That, I think, is hard to come by. By the way, if anyone is interested which podcast I am talking about, this is the episode. "The Real Problems w/ Git" on ThePrimeTime. https://youtu.be/t6qL_FbLArk?si=GOkixm86rFADoc4x https://youtu.be/t6qL_FbLArk?si=GOkixm86rFADoc4x
- pampa 1y agoI didn't think that there was something wrong with my git workflow, or that git was complicated. I switched from darcs as my primary VCS to git around 2007. I was skeptical about jj at first but gave it a try. Did not look back ever since. My impression is, that git is ok for managing shared history. And thats what i was using it for mostly. But jj added another whole dimension for managing my work in progress, different paths of code that i am working on in the moment. jj made it almost frictionless. I did not know I was missing it, but i'm not going back.
- guidopallemans 1y agoI listened to the same podcast, and agreed with the points that Casey made. However, there were some aspects of version control that were glossed over. What was described was actually quite close to developing through a Dropbox folder + (implied) tooling. And that makes a lot of sense for Casey Muratori's current work, which I believe is a small 5-10 person team doing game (engine) development. Such teams can quite easily work all in the same source branch (and this could in fact be preferred, e.g. for large assets in gaming). However, as organizations grow, you want different levels of staging (that could be provided by your version control). A split between local and _the common_ stream, release branches, splits between projects or features, review states, etc. So I believe the optimum is somewhere in the middle, and jj does take a step towards it. But still some friction remains.
- saltserv 1y ago[dead]
- infamousclyde 1y agoTo the author: I really enjoyed your style of writing. This had more explicit and realistic examples compared to other HN tutorials on the subject, and that made it easy to inhale in one sitting. Thanks for your work!
- thecupisblue 1y agoI still do not understand why use jj. It is a layer on top of git that adds its own terminology and processes. The DX doesn't come close to git in understandability, what is `jj bookmark move main --to @-` and how is it more understandable than git?
- sgjennings 1y agoI’ll focus only on the syntax of the command. Why you might need it at all is important, of course, but it’s nuanced and specific to how some people work (I never need this command or anything like it, for example). > jj bookmark move Presumably, this part is reasonably clear. “I want to move a bookmark.” > main Which bookmark to move. I think this is probably clear from context? > --to @- And here’s the part that looks foreign to a non-jj user. This syntax is familiar to jj users because the same revset syntax is used across the whole CLI. `@` is the working copy commit (the commit you have “checked out” that you are currently editing), and `@-` specifies its parent. Because it’s just a revset, you could specify that same command in a number of ways: - If you know the parent’s commit ID or change ID, you could use that instead: `--to abc123` - If there happens to be another bookmark already there, you can use its name: `--to other-feature` - You probably wouldn’t type this in the terminal, but you could do exotic things like `--to 'mutable() & description("foobar2000")'` to assign the bookmark to the work-in-progress commit that has "foobar2000" in the commit message. Revsets used pervasively are one of the things that make the DX lovely.
- thecupisblue 1y agoThanks! Just this is a 10x better explanation than most things I've seen online.
- SAI_Peregrinus 1y ago`git` is a content-addressable filesystem (the "plumbing") with a VCS UI on top of it (the "porcelain"). `jj` is alternative "porcelain" using the same "plumbing". Git was initially designed to be a toolkit on which to create VCSes, over time the VCS portion of Git has become more complete but is still a very leaky abstraction, resulting in users having to use the "plumbing" commands more often than never. `jj` aims to be better "porcelain" over the Git "plumbing", and the project authors hope to eventually support other "plumbing" model(s).