I just don't have enough pain points with Git to move to something new. I don't have a problem remembering the ~5 commands I need most on any given workday. Between stashes, branches, temporary commits I later rebase, and recently worktrees, I don't lack for anything in my usage. It's universally used across both my public and corporate life, and neither does anyone need to learn a new tool to interact with my code base, nor do I need to deal with possible inconsistencies by using a different frontend on my end.
It's cool that it exists, and it's impressive that it is built on top of git itself. If you (like the author) want to use it, then more power to you. But I have yet to be convinced by any of these articles that it is worth my time to try it since nearly all of them start from a point of "if you hate Git like me, then try this thing".
If anyone has a link to an article written from the point of view of "I love or at least tolerate git and have no real issues with it, here's why I like JJ," then I'd be glad to read it.
If you've ever lived in a world of stacked commits with develop on main (i.e. not gitflow, no feature branches), combined with code review for every commit, git will soon start to aggravate you. Git doesn't make rebasing a chain or tree of commits pleasant. Git records merge resolutions and can reuse them, but it doesn't do the same thing for rebases, making them more repetitive and tedious than they should be. When you address comments on earlier commits in a chain, you need to rebase after. Git's affordances for rebasing aren't great.
And when you rebase, the commits lose their identity since commit hashes are content-addressed, despite having an identity in people's minds - a new revision of a commit under review is usually logically the same unit of change, but git doesn't have a way of expressing this.
jj, as I understand it, addresses these pains directly.
I don't have major pain points with git either (mainly just that rebase merge conflicts can get awful to deal with), but I just love jj and I'm not looking back.
It turns out there were a lot of things that I was not doing with git because with git it would have been painful.
Now my PRs are split into human-sized commits that each contain a set of changes that make sense together, and I keep moving changes around during development to keep the history tidy, until it's time to send the pull request. If a commit introduces a typo, the typo fix should go into that commit so the typo never happened in the first place and you don't get reviews like "please fix this" and then "oh wait I see you fixed it in a later commit".
And sure, with git you could checkout the faulty commit, amend it, then amend -a and hope no one was looking, and rebase your dev branch onto the amended commit and it will often even work. Or rebase -i, sure -- have fun with it if the typo was 12 commits ago.
So I just never did that because augh.
With jj it's trivial. You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it.
No more rebase hell. No more deleting the checkout and pulling it clean because things went sideways in a way that would be hell to fix manually -- jj takes snapshots after every mutation and rolling back is easy. No more squashing on merge to sweep the messy commit history under the carpet. No more juggling index and staged files and stashed files and all that messy business. Everything is just suspiciously straightforward. To think this could have been our lives all along!
And I'm not looking back.
It's not that I dislike git. It's just that I love jj.
> Now my PRs are split into human-sized commits that each contain a set of changes that make sense together, and I keep moving changes around during development to keep the history tidy, until it's time to send the pull request. If a commit introduces a typo, the typo fix should go into that commit so the typo never happened in the first place and you don't get reviews like "please fix this" and then "oh wait I see you fixed it in a later commit".
That's my workflow in Git. It is sometimes painful, but only because other people don't do that.
It is less work, if you use git --fixup=old-commit-hash and then use git rebase --autosquash. The --fixup step can even by automated, by using git-absorb, but this needs to be installed separately.
> You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it.
That sounds the same in Git?
> No more deleting the checkout and pulling it clean because things went sideways in a way that would be hell to fix manually
When do you need to do that? The only case in which I messed up my repo, was when I had a harddrive crash and recovered commits manually from git objects, because the other files were corrupted.
> rolling back is easy.
Yes, that seams a bit easier, but reflog still exists.
> No more squashing on merge to sweep the messy commit history under the carpet.
This is just as well a stupid idea in Git and I hate that. This seams to be cultural and is not suggested by the tool itself.
> No more juggling index and staged files and stashed files
I find these useful, but you can also use Git without them. Just always use commit -a and commit instead of stashing.
> > You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it.
> That sounds the same in Git?
I've always struggled with this myself, and would like to update my git knowledge. Can you walk me through the commands to do this? Let's say the commit id is `abcd1234` and it's 5 commits ago.
In JJ I'd do this:
vim file/with/typo.txt
jj squash -into abcd1234 file/with/typo.txt
vim file/with/typo.txt
git add file/with/typo.txt
git commit --fixup=abcd1234
git rebase --autosquash -i
For some reason I need to pass --interactive/-i, even if I don't actually want it to be interactive. I am not sure if this is just a bug in my Git version or if this is intended.
The git commit step can also be replaced with git-absorb, if you have this installed and abcd1234 was the last time you modified these lines.
The second approach is this:
git rebase -i abcd1234~
# do 's/pick abcd1234/edit abcd1234/' in your editor
vim file/with/typo.txt
git rebase --continue
Where jj shines is advanced workflows that aren’t practical with git. If you aren’t interested in those then it doesn’t give you as many benefits over git.
If you are breaking down your features into small PRs, stacking them, etc…, then jj is super helpful.
The best thing that could come out of jujitsu is git itself adopting the change-id system (which I believe I read somewhere is being considered). If you actually take time to learn your tools and how they're intended to be used, there's really not reason to learn jj IMO
git is both a (bad) UI and a protocol. Jujutsu is a UI on top of git (the protocol).
There's nothing wrong with taking the time to learn how to use a bad UI, especially if there's no other option. But don't mistake your personal mastery of git for evidence that it's better than jj.
In all likelihood, the git proposal you allude to would not extend further than adding a bit of persistent metadata that follows commits after "destructive" changes. And even then, it'd be imperatively backing into the change-as-commit-graph data model rather than coming by it honestly.
> If you actually take time to learn your tools and how they're intended to be used, there's really not reason to learn jj IMO
This is like saying if people take the time to learn curl, there's really no reason to learn Firefox.
And it doesn't suggest to me that you're all that familiar with jj!
- automatic rebasing! goodbye to N+1 rebases forever
- first-class conflict resolution that doesn't force you to stop the world and fix
- the revset/template languages: incredibly expressive; nothing like it in git
- undo literally any jj action; restore the repo to any previous state. try that with the reflog...
No amount of learning git nets you any of these things.
I’m also fine with git, and have used mercurial and p4 before. I think simplicity is better in this case. I do think with more and more generated code inflating the codebase with high velocity, we need to find a better way to merge conflicts.
I don’t hate git either but you’ll meet very few people who will claim its UX is optimal. JJ’s interaction model is much simpler than git’s, and the difficulty I found is that the better you know git, the harder it is to unlearn all its quirks.
I don't hate git, I like it fine and, until recently, used it exclusively on all my projects (I still use it non-exclusively). Here's an article that's written from that viewpoint:
Idk man, the first two paragraphs
of the article very much make it sound like you hate git.
> Over the past few years, I’ve been seeing people rave about Jujutsu, and I always wanted to try it, but it never seemed worth the trouble, even though I hate git.
I read that more as "aw, fuck it, I'm starting over". Then, given what it's doing, "fuck it" -> "fuckgit" makes sense.
But hey, it's not my alias. I'm just saying that the way I read it didn't suggest hate, just a little cleverness. I can't speak for what the author was thinking.
Yeah I definitely hated Subversion, which helped push me to try Git back in the day. Actually, back then I was an `hg` guy. That battle was lost long ago though.
I think you linked to the same post as OP, though?
I wrote the post, so that's a post from the perspective of someone who doesn't hate git :P
I used bzr after SVN, but my larger point is that it's all fine, the question was whether you want to go through some short-term learning for long-term gain, or if you want to keep using what you know. Either is fine, I'm still using vim as my editor, for example.
SVN was not fine. Branching took forever (all the copying). And the space that required ... In fact, lots of things took forever on large-ish repos. Remember that everything required the server and network and disk speeds were slower back then. And just a commit could destroy your work if you got stuck in a conflict resolution. So you'd have to copy all the files you changed to a backup just in case, then delete them if the resolution went OK etc.
Was it better than CVS in some way? Sure.
But git is just better in so many ways. Back in the day I used git exclusively with git-svn at a place that was still stuck with SVN and I had a blast, while everyone else didn't. I just never had any of the problems they did.
I'm not entirely sure what pain people speak of with git. I found the transition very natural. And don't come talking to me about the "weird command syntax". Some of that was specifically to be compatible / "intuitive" / what they were used to for people coming from tools like SVN.
Sure you gotta learn about "the index", understand that everything is local and that you have an origin and local copy of all the labels (also sometimes called branches or tags) you can attach to commits. That's about it for the normal and regular use that someone would've had with SVN.
Except that it has to first be true that jj is better ;)
You start out the article with hate for git without explaining what you actually don't like, then here on HN say "I don't hate git". A command called `fuckgit`? Because you need to re-clone? What are the things you commonly do that require this? I've never encountered it. Maybe you're just too advanced a user for git and jj really is better for you. But for us lowly regular users I really do not see an issue.
Some of the benefits you tout, like "editing a commit and you don't need to commit it yourself"? I'm sorry but I want to be the one in control here. I am the one that says "I'm done here, yes this is the new version of the commit I'm comfortable with". I've specifically forbid Claude to add, commit, push etc. for example.
It also breaks your "you need to stash" argument. I don't stash. I just commit if I have something WIP that needs saving while I work on some other emergency. There's no reason not to just commit. In fact I do that all the time to checkpoint work and I amend commits all the time. It's my standard commit command actually `git commit -a --amend`.
Automatic "oplog" of everything Claude did, IDE style: sure, maybe. Though I've yet to see that need arise in practice. Just because I have Claude et. al. now, I don't believe changes should be any bigger than they used to. Nor should my "commit early, commit often, push later" practice change.
> You start out the article with hate for git without explaining what you actually don't like
I start out the article saying I never understood git, and why does it matter what I don't like? That would only matter if I were trying to say that git is bad, but I'm not making a comparison. I just think jj is better-designed, and that you should try it.
> Some of the benefits you tout, like "editing a commit and you don't need to commit it yourself"?
I never said that's a benefit, I just said that's something jj does differently. I `jj commit` when I'm done with some work anyway.
> It also breaks your "you need to stash" argument. I don't stash. I just commit if I have something WIP that needs saving while I work on some other emergency.
In that case, you'll like jj, as it handles all that for you.
Your comment is coming off as a bit defensive, I didn't write my article to attack git. If you like git, keep using it, I prefer jj and I think other people will too. It's hard to get started with because its workflow is different from what we're used to, so I wrote the tutorial to help.
I didn't write my article to attack git [...] I wrote the tutorial to help.
Except you didn't write a tutorial. You wrote an "I hate git and jj is better and if you think otherwise you're wrong" article.
Blue speech bubble with literally the text: "If you don't like Jujutsu, you're wrong". This is text. There's no "tongue in cheek" voice and body language here, even if potentially you meant it that way. But given how the article itself starts, I don't think there was any of that to transport :shrug:
Needless to say, I just don’t get git
Actually, it does bear saying. And I do think that if you say "everyone that doesn't think jj is better is wrong" you have to explain what you really don't like or get. No it's not needless, because not everyone has your experience. I really do not understand your pain points unless you explain them, because I've never felt them. Either because I did understand the part you didn't, because I don't need to understand that part to use it well (cutting the decision/knowledge tree in your head is a skill by itself I've found over the years - sometimes you do have to accept magic! E.g. I don't need to understand exactly how any specific LLM works to use it well) or because I simply never had a need for the kinds of feature that trip you up.
> I just said that's something jj does differently.
Except Git doesn't do it differently here. Git only provides an additional way to commit temporary changes, you still can commit them how you like. In fact a stash are just two commits.
Before jj came along (or rather, before it reached my threshold of awareness), I was such a person. Started with git, switched to mercurial, wanted to work against github so tried sapling, loved it and started telling people about it.
I probably would have stuck with Sapling, but my company switched to git and the jj integration was cleaner -- especially being able to run in colocated mode: your project root directory has both .jj/ and .git/ subdirectories, and you can use both jj and git commands without much trouble. If someone gives me a git commit hash, I can just use it directly with jj.
Sapling is good. I'm still fond of it, and in fact still have a few repositories I haven't switched over yet. But being able to do everything with a single tool is useful, plus jj gives me some extra capabilities over sapling (or at least things that I don't know how to do as easily).
I have been trying Jujutsu for a few weeks. It's cool and I like trying new things. I wouldn't say that it's so much better than git, though; there is nothing that I miss in the projects where I use git.
On the other hand, I have issues with Jujutsu, one of which completely prevents me from using it in some projects:
* No support for git submodules. One can dislike submodules as much as they want, if I need to contribute to a repository using them, I can't use Jujutsu.
* The signing support is very annoying with a security key. Even if I configure 'sign-on-push', it will access the security key every time it tries to check the signature, which is pretty much every `jj st` or `jj log` after something has changed locally. I don't need to check my own signatures, IMO they should be checked on fetch and on push.
* There is no way to configure a 'defaultKeyCommand' like in git, which I now rely on (because I have multiple security keys).
> Needless to say, I just don’t get git. I never got it, even though I’ve read a bunch of stuff on how it represents things internally. I’ve been using it for years knowing what a few commands do, and [...]
> If you don't like Jujutsu, you're wrong
It would be much more convincing if they had any idea of git that they were comparing it to.
I really loved jujutsu for the few weeks that I used it.
However, I did find all my tools that rely on Git (eg Gitlab CLI that can open merge request from the current branch) breaking because JJ operations result in detached head in Git.
In addition, mixing Git and JJ will result in your repos becoming really slow when you do need to run some Git operation.
I also use them, because I don't know a better alternative. I want it the subproject's version to be defined in a parent's commit and also modify the subproject. Changes to the subproject should stay in the commit history of the subproject Is there a better way?
One of the bigger selling points of JJ just wouldn't work so well without larger team buy in for me: the ability to push stacked PRs.
I like the idea of it, but there's so much inertia around typical git workflows that revolve around the GH pull request model (with the only difference being the use of trunk based dev or some git-flow like branching strategy) that it'd be hard to change without a lot of buy in.
I still think back to Phabricator and its approach to code review, noting that it sadly never got wider traction despite having notable benefits over a completely entrenched status quo.
What is there not to _get_, honestly? And why is jj so easier to get?
The author seems to focus on how great it is to make changes to your commit history locally, and that you shouldn't worry because it's not pushed yet.
The thing is, I don't want automatic. Automatic sucks. The point of version control is that I am able to curate my changes. The guards and rails of git is what makes me feel safe.
I am still failing to see why JJ is superior to git, or whatever.
There are some convention people follow when working with git to make it safe to use. But those aren't git's features -- they are ways to avoid confusion.
If you don't want automatic, you shouldn't use git. It does too many things automatically, like update your branches' heads whenever you commit, for example.
And if I don't want that I can detach the HEAD. This isn't to much different. The only thing that changes by using branches is that you have a nice name, it prevents the commits from being GCed and it provides a default name on push.
I have been trying to use jj for a couple months now, but hitting some friction with my company’s GitHub PR workflow. Specifically, after the PR is merged, the next time I fetch I always end up with a ton of conflicts. It gets hard to clean them up, so I often end up abandoning all mutable commits to start fresh.
I feel like I’m doing something wrong, as I haven’t seen this mentioned in any tutorials, but I don’t know what! :-/
I’ve been using jj for a few months now and still love its workflow, but I keep running into the same problem you mentioned. The advantages of jj far outweigh this issue, so I’d really like to figure out a clean way to avoid these conflicts.
for me, squash merges are enforced on github, and usually results in some weird / empty commits if i rebase a local stack after pulling in changes with part of the stack merged.
It’s also possible that I start my next task without remembering to create a new diff first. That might explain the conflict when the original commit becomes immutable?
> Jujutsu, in contrast, is more like playing with Play-Doh. You take a lump, cut it into two, shape one piece into something, give it a name, change your mind, give it another name, take a bit of the second piece and stick it on the first piece, and generally go back and forth all around your play area, making changes.
I love this description and it describes how I work with git. When I’m doing things locally I’m constantly committing small wip commits. When I get something the way I like it I’ll interactive rebase/just back it all up, and then create the perfect little boxes. I guess I should try jujutsu since it sounds like it might be even more for me. Although if you can’t get to the perfect boxes at the end I don’t know if I’d like it.
That's how I feel like working with git locally using a combination of basic commands and gitup (https://gitup.co/), that may be why I couldn't really get the selling point of jj when I tried it a couple weeks ago.
The only part that piqued my interest is merges being always successful and conflicts just sitting in the tree, waiting patiently to be resolved... It's the next logical step after being able to commit without synchronizing when we all moved away from SVN.
I think you would love jj then. It is dead-simple to just move things around - branches/bookmarks, commits and even single lines of code within a diff.
Always the same starting point: "I don't understand how git works".
If you can't understand git, one of the most used tool in the whole industry, this is a *you* problem. You MUST take the time to understand how it works properly. Every job you'll get and every projects you'll work on will use a Version Control (at least I hope).
Abstracting this knowledge by using a tool that does things quite differently won't help you at all on the long run.
I am a git expert and I very much prefer jj. It enables workflows that are impractical with git. It’s hard to even imagine these workflows if you only use git because your thinking is constrained by the limitations of your tools.
Git rebase is like programming with punch cards compared to jj’s rebase being like writing Python.
Well then articles should focus on that if they want to convince people who use git as a daily driver. Currently the impression I get from jj is that it's "git for people who have a hard time understanding/using git", therefore since I don't have a hard time understanding/using git, jj is not for me.
Maybe more articles showing galaxy brain SCM workflows that are difficult under git but possible under jj and are killer for productivity is a better marketing strategy for jj.
I wholeheartedly agree with you. What makes jj a killer app to me is that it allows me to work with source control in a whole new way that just feels so much more powerful to me. I haven't felt like this since I first discovered git after dealing with the pain of subversion.
Ok, I can get behind JFK's quote "We choose to go to the Moon not because it is easy, but because it is hard" - but do we have to apply the same quote to git? The way I see it, git is a tool and not a goal in and of itself. If there is a tool that does the same thing in an easier to use way (and can work with git repos), why use git? Of course, using VCS is part of the job description of almost every developer in the world, but git !== VCS...
"if some students fail the test, the problem is of the students, if many do, is of the teacher".
Git is a bad teacher. There are a lot of things that are profound yet easy to grasp when learned and other things are called bad products. Git is one of them.
> You MUST take the time to understand how it works properly.
Unfortunately, I agree.
It is both ubiquitous and so unnecessarily complex. The fact that all developers are required to memorize at least a few of its inscrutable incantations reflects poorly on the industry and on the judgement of its practitioners.
I use a gui for 90% of my workflows. Another 9 percent points are hitting back in my console history to rerun commands, never mind if git or jj or POSIX that affect my working dir or index state.
What am I supposed to do, use the UI plus jj, and prompt an LLM to use which: git, or jj, in case I am too lazy to think of the right command in the remaining one percent of cases?
But in general, I like the "less states and DVCS features than git" approach, but would not switch back to mercurial just to avoid the whole "should we rebase or create merge-commits" discussions in our teams due to having a single default that might not be optimal for everyone, but just works.
use jjui - its an absolute pleasure to use as you dont need to know anything beyond arrow keys and some keyboard shortcuts (which you can also find in the ? help menu). https://github.com/idursun/jjui
If it doesnt do anything you already need, then the maintainer is likely to add it quickly - its rare to find someone so responsive
I feel like anyone who spends just a couple of hours learning git will have a much better mental model than the crappy "Assembly line" model from the article.
Your real mental model of git should be an acyclic directed graph where the nodes are commits and the edges are ancestry. Commits represents snapshot of the project's state. Tags and branches are just text pointers to commits in the graph.
If you use this mental model, suddenly things like git rebase or git reset become far less mysterious and arcane since they are just simple graph operations. Like `git reset --hard X` means "Make current branch's text pointer point to X"
I think the author is one of those folks who were able to fully grasp the beauty of the Git data model for the first time by switching to Jujutsu. It makes it easier to see the “DAG of commits” vision than Git with its index and stashes and confusingly named commands with fifty flags.
Yeah, exactly, and I've fruitlessly read too many guides on git's data model.
What was holding me back turned out to be the fact that git has too much magic (it updates branches automatically when you commit, rebasing "does stuff", conflict resolution was just arcane).
Jj exposes all that into simple, composable principles, making everything click.
> What was holding me back turned out to be the fact that git has too much magic
Considering jj is built on top of git, doesn't that mean jj has even more magic? That's like saying React is too magical so we should use Next.js instead (which is built on React).
Maybe you just mean that jj has a more intuitive CLI than git?
Jj uses git's data model, that doesn't mean it uses git commands for everything under the hood. Creating a commit with jj doesn't move the branch tag automatically, whereas git does. That's what confused me with git, it didn't expose the internals enough, so even though I had read about the data structures, it never clicked what was changed when, because git did it under the hood.
I understand git at a pretty deep level. I still very much prefer jujutsu. Its rebase is just so much more powerful than git. I regularly work on top of octopus merges in jj of all my in-review parallel PRs and when I want to rebase them all and the octopus merge and the various anonymous branches on top it takes 1 command. It’s so much more powerful than git it’s crazy.
Totally agree on the DAG point of view, but I would argue that for different people you need different analogies/models to make it click. I would argue that pointing towards graph theory might help people that have a formal CS or maths education, but not necessarily folks that went through bootcamps, switched from design roles, have a biology background (e.g. bioinformatics) or do statistics (e.g. in medicine or psychology)
In the age of Claude Code and other MCPs, the last thing I want is my commit history to be mutable. I've added instructions to Claude which make a commit before each modification with a summary of the conversation that caused the change. Once I'm happy with the work, I squash the commits and push up. (Which I believe is more or less equivalent to the jj workflow.)
This flow can work with jj also. It would probably be exactly the same. You'd do `jj new` and have Claude set the description and make its changes. When you're ready for the next round, you'd repeat and do `jj new` again for the next revision.
I think jj's mutable revisions are best thought of as automation around `git commit --amend && rebase_everything_after_this_commit`. If you're not using that kind of flow with Claude, you wouldn't use that kind of flow with jj either.
My data point is the Mozilla monorepo. My .git directory is 5.5GB, so half of what you're talking about. jj speed has not been a problem at all. Some thing are sped up a bit by enabling watchman, but I didn't bother for the first 4 months or so that I used it because the speed was already fine and I didn't want to add another point of failure. (And in fact, when I first enabled it, it slowed things down because the checkout is too big and hit inotify limits.)
I don't have very many branches, though. 13 branches, 6838 tags.
Some caveats: jj's version of `blame` (jj file annotate) is painfully slow and I usually run `git blame` instead. (Which is a general thing: if anything is missing or slow, you can always just do it with git.) jj's rebase is insanely fast -- especially if you add in the time to manually resolve conflicts, since a good chunk of the time I don't have to spend any time at all since the conflicts are only in experimental twigs that I may never need to go back to (and if I do, it's fine to wait until I need it).
I have primarily used git in the terminal for more than a decade. I also used magit when I was primarily working in emacs (magit's great!). I now primarily use lazygit. While I'm not a fan of the whole UI, this is the only git tool that makes me go super fast while creating a near-perfect commit history. I tried using jj but immediately stopped after installation as it required a learning curve that I wasn't ready to commit to yet.
you might consider trying again, but do so with jjui (https://github.com/idursun/jjui) - very similar concept to lazygit and makes working with (the already simple) jj even more seamless and intuitive
I don't really understand the appeal of jj as someone who uses sublime merge [0].
It has good support for submodules, a lot of the editing commits (messages, squash, move etc...) is really easy and I can also see and edit my stashes directly. Is there any benefit to jj compared to this?
Until jj supports `git rebase -x "cargo check --deny warnings"`, it's useless to me. jj has primitive support for fixing individual files that changed, but it cannot work on any linter or formatter that depends on other files.
Depends on what you mean. "Checking out" is ambiguous, and in fact isn't jj terminology. As git terminology, it could mean switching branches or showing file contents or going to a detached HEAD or resetting file contents.
If you want the contents of the file at some old commit 0a123, `jj file show -r 0a123 <filename>`. If you want to overwrite the current version of a file with the version from 0a123, `jj restore --from 0a123 <filename>`.
How do you "checkout single files" in git? What does that mean?
> How do you "checkout single files" in git? What does that mean?
git checkout 0a123 -- <filename>
So the answer is jj restore. Thanks.
Checkout means that the version of some files at some commit is "checked out" in the worktree. So all these things are mostly the same in Git terms. The arbitrary split into switch and restore is confusing to me.
git rebase|cherry-pick|revert --abort and git reflog can solve pretty much all of my problems with git repos in weird states, and any advanced Git user should know them.
what im most impressed by when I read the comments to jj-related threads is how many people are handwriting assembly code.
I come to this conclusion because there's always a large amount of people saying "if you dont understand, let alone have mastered, git, then you dont get to have an opinion"
So, clearly these people similarly dont use ease-of-use abstractions like programming languages
"Git is too hard" is never a good argument to promote the use of a different tool.
I use git on the terminal exclusively, never had an issue amending a commit or rebasing a branch, or even dealing with conflict resolution most of the time I just use one of the automatic strategies.
> "Git is too hard" is never a good argument to promote the use of a different tool.
Really? Pointing out that a tool is difficult to use seems like an excellent argument to promote the use of a different (supposedly simpler) tool.
Specifically in the case of git, I'm glad it was not difficult for you, but it is undeniable that it is a very difficult tool for many people to learn.
I just don't have enough pain points with Git to move to something new. I don't have a problem remembering the ~5 commands I need most on any given workday. Between stashes, branches, temporary commits I later rebase, and recently worktrees, I don't lack for anything in my usage. It's universally used across both my public and corporate life, and neither does anyone need to learn a new tool to interact with my code base, nor do I need to deal with possible inconsistencies by using a different frontend on my end.
It's cool that it exists, and it's impressive that it is built on top of git itself. If you (like the author) want to use it, then more power to you. But I have yet to be convinced by any of these articles that it is worth my time to try it since nearly all of them start from a point of "if you hate Git like me, then try this thing".
If anyone has a link to an article written from the point of view of "I love or at least tolerate git and have no real issues with it, here's why I like JJ," then I'd be glad to read it.
If you've ever lived in a world of stacked commits with develop on main (i.e. not gitflow, no feature branches), combined with code review for every commit, git will soon start to aggravate you. Git doesn't make rebasing a chain or tree of commits pleasant. Git records merge resolutions and can reuse them, but it doesn't do the same thing for rebases, making them more repetitive and tedious than they should be. When you address comments on earlier commits in a chain, you need to rebase after. Git's affordances for rebasing aren't great.
And when you rebase, the commits lose their identity since commit hashes are content-addressed, despite having an identity in people's minds - a new revision of a commit under review is usually logically the same unit of change, but git doesn't have a way of expressing this.
jj, as I understand it, addresses these pains directly.
> Git records merge resolutions and can reuse them, but it doesn't do the same thing for rebases
Since when does rerere not work with rebase anymore?
I think it does but rerere is not nearly as good as first class conflicts in jj
Ok, but by that measure,
>> Git records merge resolutions
isn't true either.
I don't have major pain points with git either (mainly just that rebase merge conflicts can get awful to deal with), but I just love jj and I'm not looking back.
It turns out there were a lot of things that I was not doing with git because with git it would have been painful.
Now my PRs are split into human-sized commits that each contain a set of changes that make sense together, and I keep moving changes around during development to keep the history tidy, until it's time to send the pull request. If a commit introduces a typo, the typo fix should go into that commit so the typo never happened in the first place and you don't get reviews like "please fix this" and then "oh wait I see you fixed it in a later commit".
And sure, with git you could checkout the faulty commit, amend it, then amend -a and hope no one was looking, and rebase your dev branch onto the amended commit and it will often even work. Or rebase -i, sure -- have fun with it if the typo was 12 commits ago.
So I just never did that because augh.
With jj it's trivial. You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it.
No more rebase hell. No more deleting the checkout and pulling it clean because things went sideways in a way that would be hell to fix manually -- jj takes snapshots after every mutation and rolling back is easy. No more squashing on merge to sweep the messy commit history under the carpet. No more juggling index and staged files and stashed files and all that messy business. Everything is just suspiciously straightforward. To think this could have been our lives all along!
And I'm not looking back.
It's not that I dislike git. It's just that I love jj.
> Now my PRs are split into human-sized commits that each contain a set of changes that make sense together, and I keep moving changes around during development to keep the history tidy, until it's time to send the pull request. If a commit introduces a typo, the typo fix should go into that commit so the typo never happened in the first place and you don't get reviews like "please fix this" and then "oh wait I see you fixed it in a later commit".
That's my workflow in Git. It is sometimes painful, but only because other people don't do that.
It is less work, if you use git --fixup=old-commit-hash and then use git rebase --autosquash. The --fixup step can even by automated, by using git-absorb, but this needs to be installed separately.
> You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it.
That sounds the same in Git?
> No more deleting the checkout and pulling it clean because things went sideways in a way that would be hell to fix manually
When do you need to do that? The only case in which I messed up my repo, was when I had a harddrive crash and recovered commits manually from git objects, because the other files were corrupted.
> rolling back is easy.
Yes, that seams a bit easier, but reflog still exists.
> No more squashing on merge to sweep the messy commit history under the carpet.
This is just as well a stupid idea in Git and I hate that. This seams to be cultural and is not suggested by the tool itself.
> No more juggling index and staged files and stashed files
I find these useful, but you can also use Git without them. Just always use commit -a and commit instead of stashing.
> > You just switch to that commit, fix the typo, and switch back to where you were. Or fix the typo where you were and squash the fix, and only the fix, into the commit that introduced it.
> That sounds the same in Git?
I've always struggled with this myself, and would like to update my git knowledge. Can you walk me through the commands to do this? Let's say the commit id is `abcd1234` and it's 5 commits ago.
In JJ I'd do this:
Or if I was feeling more pedantic I'd do:You have the same two options in Git:
For some reason I need to pass --interactive/-i, even if I don't actually want it to be interactive. I am not sure if this is just a bug in my Git version or if this is intended.The git commit step can also be replaced with git-absorb, if you have this installed and abcd1234 was the last time you modified these lines.
The second approach is this:
Heres a great article about a powerful workflow that jj makes practical https://ofcr.se/jujutsu-merge-workflow/
Where jj shines is advanced workflows that aren’t practical with git. If you aren’t interested in those then it doesn’t give you as many benefits over git.
If you are breaking down your features into small PRs, stacking them, etc…, then jj is super helpful.
The best thing that could come out of jujitsu is git itself adopting the change-id system (which I believe I read somewhere is being considered). If you actually take time to learn your tools and how they're intended to be used, there's really not reason to learn jj IMO
git is both a (bad) UI and a protocol. Jujutsu is a UI on top of git (the protocol).
There's nothing wrong with taking the time to learn how to use a bad UI, especially if there's no other option. But don't mistake your personal mastery of git for evidence that it's better than jj.
In all likelihood, the git proposal you allude to would not extend further than adding a bit of persistent metadata that follows commits after "destructive" changes. And even then, it'd be imperatively backing into the change-as-commit-graph data model rather than coming by it honestly.
> If you actually take time to learn your tools and how they're intended to be used, there's really not reason to learn jj IMO
This is like saying if people take the time to learn curl, there's really no reason to learn Firefox.
And it doesn't suggest to me that you're all that familiar with jj!
- automatic rebasing! goodbye to N+1 rebases forever
- first-class conflict resolution that doesn't force you to stop the world and fix
- the revset/template languages: incredibly expressive; nothing like it in git
- undo literally any jj action; restore the repo to any previous state. try that with the reflog...
No amount of learning git nets you any of these things.
I’m also fine with git, and have used mercurial and p4 before. I think simplicity is better in this case. I do think with more and more generated code inflating the codebase with high velocity, we need to find a better way to merge conflicts.
I don’t hate git either but you’ll meet very few people who will claim its UX is optimal. JJ’s interaction model is much simpler than git’s, and the difficulty I found is that the better you know git, the harder it is to unlearn all its quirks.
I don't hate git, I like it fine and, until recently, used it exclusively on all my projects (I still use it non-exclusively). Here's an article that's written from that viewpoint:
https://www.stavros.io/posts/switch-to-jujutsu-already-a-tut...
That having been said, I didn't hate Subversion either. It was fine.
> I don't hate git
Idk man, the first two paragraphs of the article very much make it sound like you hate git.
> Over the past few years, I’ve been seeing people rave about Jujutsu, and I always wanted to try it, but it never seemed worth the trouble, even though I hate git.
Also:
> I don't hate git
but
> I have my trusty alias, fuckgit
Someone who doesn't hate git would have named this alias quite differently...
I read that more as "aw, fuck it, I'm starting over". Then, given what it's doing, "fuck it" -> "fuckgit" makes sense.
But hey, it's not my alias. I'm just saying that the way I read it didn't suggest hate, just a little cleverness. I can't speak for what the author was thinking.
Fair enough, I'll clarify what I actually hate.
Yeah I definitely hated Subversion, which helped push me to try Git back in the day. Actually, back then I was an `hg` guy. That battle was lost long ago though.
I think you linked to the same post as OP, though?
I wrote the post, so that's a post from the perspective of someone who doesn't hate git :P
I used bzr after SVN, but my larger point is that it's all fine, the question was whether you want to go through some short-term learning for long-term gain, or if you want to keep using what you know. Either is fine, I'm still using vim as my editor, for example.
SVN was not fine. Branching took forever (all the copying). And the space that required ... In fact, lots of things took forever on large-ish repos. Remember that everything required the server and network and disk speeds were slower back then. And just a commit could destroy your work if you got stuck in a conflict resolution. So you'd have to copy all the files you changed to a backup just in case, then delete them if the resolution went OK etc.
Was it better than CVS in some way? Sure.
But git is just better in so many ways. Back in the day I used git exclusively with git-svn at a place that was still stuck with SVN and I had a blast, while everyone else didn't. I just never had any of the problems they did.
I'm not entirely sure what pain people speak of with git. I found the transition very natural. And don't come talking to me about the "weird command syntax". Some of that was specifically to be compatible / "intuitive" / what they were used to for people coming from tools like SVN.
Sure you gotta learn about "the index", understand that everything is local and that you have an origin and local copy of all the labels (also sometimes called branches or tags) you can attach to commits. That's about it for the normal and regular use that someone would've had with SVN.
Well you can either have a viewpoint of "the current thing I use is fine because I'm used to the warts" or "it's not fine because other things exist".
It can't be that SVN is bad and git is better but also that git is fine even though jj is better.
Except that it has to first be true that jj is better ;)
You start out the article with hate for git without explaining what you actually don't like, then here on HN say "I don't hate git". A command called `fuckgit`? Because you need to re-clone? What are the things you commonly do that require this? I've never encountered it. Maybe you're just too advanced a user for git and jj really is better for you. But for us lowly regular users I really do not see an issue.
Some of the benefits you tout, like "editing a commit and you don't need to commit it yourself"? I'm sorry but I want to be the one in control here. I am the one that says "I'm done here, yes this is the new version of the commit I'm comfortable with". I've specifically forbid Claude to add, commit, push etc. for example.
It also breaks your "you need to stash" argument. I don't stash. I just commit if I have something WIP that needs saving while I work on some other emergency. There's no reason not to just commit. In fact I do that all the time to checkpoint work and I amend commits all the time. It's my standard commit command actually `git commit -a --amend`.
Automatic "oplog" of everything Claude did, IDE style: sure, maybe. Though I've yet to see that need arise in practice. Just because I have Claude et. al. now, I don't believe changes should be any bigger than they used to. Nor should my "commit early, commit often, push later" practice change.
> You start out the article with hate for git without explaining what you actually don't like
I start out the article saying I never understood git, and why does it matter what I don't like? That would only matter if I were trying to say that git is bad, but I'm not making a comparison. I just think jj is better-designed, and that you should try it.
> Some of the benefits you tout, like "editing a commit and you don't need to commit it yourself"?
I never said that's a benefit, I just said that's something jj does differently. I `jj commit` when I'm done with some work anyway.
> It also breaks your "you need to stash" argument. I don't stash. I just commit if I have something WIP that needs saving while I work on some other emergency.
In that case, you'll like jj, as it handles all that for you.
Your comment is coming off as a bit defensive, I didn't write my article to attack git. If you like git, keep using it, I prefer jj and I think other people will too. It's hard to get started with because its workflow is different from what we're used to, so I wrote the tutorial to help.
Blue speech bubble with literally the text: "If you don't like Jujutsu, you're wrong". This is text. There's no "tongue in cheek" voice and body language here, even if potentially you meant it that way. But given how the article itself starts, I don't think there was any of that to transport :shrug:
Actually, it does bear saying. And I do think that if you say "everyone that doesn't think jj is better is wrong" you have to explain what you really don't like or get. No it's not needless, because not everyone has your experience. I really do not understand your pain points unless you explain them, because I've never felt them. Either because I did understand the part you didn't, because I don't need to understand that part to use it well (cutting the decision/knowledge tree in your head is a skill by itself I've found over the years - sometimes you do have to accept magic! E.g. I don't need to understand exactly how any specific LLM works to use it well) or because I simply never had a need for the kinds of feature that trip you up.> I just said that's something jj does differently.
Except Git doesn't do it differently here. Git only provides an additional way to commit temporary changes, you still can commit them how you like. In fact a stash are just two commits.
Oh, if you’re an ex-hg guy, this makes this easier, then: jj is in many ways a renaissance for hg’s philosophy: https://ahal.ca/blog/2024/jujutsu-mercurial-haven/
I wonder if there's a parallel universe where people are writing posts about Sapling and getting mercurial users to migrate to it.
Before jj came along (or rather, before it reached my threshold of awareness), I was such a person. Started with git, switched to mercurial, wanted to work against github so tried sapling, loved it and started telling people about it.
I probably would have stuck with Sapling, but my company switched to git and the jj integration was cleaner -- especially being able to run in colocated mode: your project root directory has both .jj/ and .git/ subdirectories, and you can use both jj and git commands without much trouble. If someone gives me a git commit hash, I can just use it directly with jj.
Sapling is good. I'm still fond of it, and in fact still have a few repositories I haven't switched over yet. But being able to do everything with a single tool is useful, plus jj gives me some extra capabilities over sapling (or at least things that I don't know how to do as easily).
I worked with SVN and I hated it, merging branches and dealing with conflict resolution on SVN was like getting stepped on the balls
I have been trying Jujutsu for a few weeks. It's cool and I like trying new things. I wouldn't say that it's so much better than git, though; there is nothing that I miss in the projects where I use git.
On the other hand, I have issues with Jujutsu, one of which completely prevents me from using it in some projects:
* No support for git submodules. One can dislike submodules as much as they want, if I need to contribute to a repository using them, I can't use Jujutsu.
* The signing support is very annoying with a security key. Even if I configure 'sign-on-push', it will access the security key every time it tries to check the signature, which is pretty much every `jj st` or `jj log` after something has changed locally. I don't need to check my own signatures, IMO they should be checked on fetch and on push.
* There is no way to configure a 'defaultKeyCommand' like in git, which I now rely on (because I have multiple security keys).
Yeah, it sounds like you have specific requirements that don't let you use jj until it gets support for those. That's fair.
I also have that problem with submodules. Of course they are crap, but the project uses them.
> Needless to say, I just don’t get git. I never got it, even though I’ve read a bunch of stuff on how it represents things internally. I’ve been using it for years knowing what a few commands do, and [...]
> If you don't like Jujutsu, you're wrong
It would be much more convincing if they had any idea of git that they were comparing it to.
Except, the fact that I have no idea of git after 20 years of use, whereas I have a great idea of jj after two months is exactly the point.
Fair enough. I'll reconsider if my git workflow is impacted to a point where it shows up to be non-negligible under Amdahl's Law.
Edit: read more of the post and I still don't see the big deal. It's like rebase/edit with a bit less typing.
‘A bit less typing’ is the point, it makes a painful workflow into a pleasurable one.
I really loved jujutsu for the few weeks that I used it. However, I did find all my tools that rely on Git (eg Gitlab CLI that can open merge request from the current branch) breaking because JJ operations result in detached head in Git.
In addition, mixing Git and JJ will result in your repos becoming really slow when you do need to run some Git operation.
Hm, I can't speak to the tools, I imagine you're right. I haven't found any slowness, though. Why would jj slow git down?
I also use them, because I don't know a better alternative. I want it the subproject's version to be defined in a parent's commit and also modify the subproject. Changes to the subproject should stay in the commit history of the subproject Is there a better way?
One of the bigger selling points of JJ just wouldn't work so well without larger team buy in for me: the ability to push stacked PRs.
I like the idea of it, but there's so much inertia around typical git workflows that revolve around the GH pull request model (with the only difference being the use of trunk based dev or some git-flow like branching strategy) that it'd be hard to change without a lot of buy in.
I still think back to Phabricator and its approach to code review, noting that it sadly never got wider traction despite having notable benefits over a completely entrenched status quo.
Right in the first paragraph.
> Needless to say, I just don’t get git.
What is there not to _get_, honestly? And why is jj so easier to get?
The author seems to focus on how great it is to make changes to your commit history locally, and that you shouldn't worry because it's not pushed yet.
The thing is, I don't want automatic. Automatic sucks. The point of version control is that I am able to curate my changes. The guards and rails of git is what makes me feel safe.
I am still failing to see why JJ is superior to git, or whatever.
Hmm, what guards and rails?
There are some convention people follow when working with git to make it safe to use. But those aren't git's features -- they are ways to avoid confusion.
JJ rebase coupled with committable conflicts is very much superior to git.
It's not that it is superior, it is completely inferior to git :) That is why you are failing to see :)
If you don't want automatic, you shouldn't use git. It does too many things automatically, like update your branches' heads whenever you commit, for example.
And if I don't want that I can detach the HEAD. This isn't to much different. The only thing that changes by using branches is that you have a nice name, it prevents the commits from being GCed and it provides a default name on push.
I have been trying to use jj for a couple months now, but hitting some friction with my company’s GitHub PR workflow. Specifically, after the PR is merged, the next time I fetch I always end up with a ton of conflicts. It gets hard to clean them up, so I often end up abandoning all mutable commits to start fresh.
I feel like I’m doing something wrong, as I haven’t seen this mentioned in any tutorials, but I don’t know what! :-/
I’ve been using jj for a few months now and still love its workflow, but I keep running into the same problem you mentioned. The advantages of jj far outweigh this issue, so I’d really like to figure out a clean way to avoid these conflicts.
What does git think of the tree after you pull? Does everything seem fine to git, but jj shows a conflict?
That's really odd, maybe the tree is somehow messed up? I've never had this problem. What's conflicting?
Can you try it on a fresh clone and see if it still happens?
Maybe it’s based on whether the GitHub merge is a squash, rebase, or plain merge? Or do folks usually manually perform the merge with jj?
It shouldn't matter, under the hood the tree is the same for both. I don't know why jj would complain but git wouldn't, hm.
I wonder if they've got files tracked by git-lfs. `jj` doesn't handle those yet.
for me, squash merges are enforced on github, and usually results in some weird / empty commits if i rebase a local stack after pulling in changes with part of the stack merged.
It’s also possible that I start my next task without remembering to create a new diff first. That might explain the conflict when the original commit becomes immutable?
Are you making MRs from other branches in the same repo, or are you making e.g. main to main MRs from your own fork?
I build a few diffs off of my local main, create and push a bookmark, and then create a PR back to main from that bookmark.
> Jujutsu, in contrast, is more like playing with Play-Doh. You take a lump, cut it into two, shape one piece into something, give it a name, change your mind, give it another name, take a bit of the second piece and stick it on the first piece, and generally go back and forth all around your play area, making changes.
I love this description and it describes how I work with git. When I’m doing things locally I’m constantly committing small wip commits. When I get something the way I like it I’ll interactive rebase/just back it all up, and then create the perfect little boxes. I guess I should try jujutsu since it sounds like it might be even more for me. Although if you can’t get to the perfect boxes at the end I don’t know if I’d like it.
That's how I feel like working with git locally using a combination of basic commands and gitup (https://gitup.co/), that may be why I couldn't really get the selling point of jj when I tried it a couple weeks ago.
The only part that piqued my interest is merges being always successful and conflicts just sitting in the tree, waiting patiently to be resolved... It's the next logical step after being able to commit without synchronizing when we all moved away from SVN.
> gitup (https://gitup.co/)
That looks actually nice, but it seams to require macOS.
I think you would love jj then. It is dead-simple to just move things around - branches/bookmarks, commits and even single lines of code within a diff.
jjui (https://github.com/idursun/jjui) makes it all that much easier too
I'll say that Jujutsu makes the way to get to the perfect boxes really friction-free.
In the past 2 months, I saw 3 articles about JJ.
Always the same starting point: "I don't understand how git works".
If you can't understand git, one of the most used tool in the whole industry, this is a *you* problem. You MUST take the time to understand how it works properly. Every job you'll get and every projects you'll work on will use a Version Control (at least I hope).
Abstracting this knowledge by using a tool that does things quite differently won't help you at all on the long run.
I am a git expert and I very much prefer jj. It enables workflows that are impractical with git. It’s hard to even imagine these workflows if you only use git because your thinking is constrained by the limitations of your tools.
Git rebase is like programming with punch cards compared to jj’s rebase being like writing Python.
https://ofcr.se/jujutsu-merge-workflow/
Well then articles should focus on that if they want to convince people who use git as a daily driver. Currently the impression I get from jj is that it's "git for people who have a hard time understanding/using git", therefore since I don't have a hard time understanding/using git, jj is not for me.
Maybe more articles showing galaxy brain SCM workflows that are difficult under git but possible under jj and are killer for productivity is a better marketing strategy for jj.
I wholeheartedly agree with you. What makes jj a killer app to me is that it allows me to work with source control in a whole new way that just feels so much more powerful to me. I haven't felt like this since I first discovered git after dealing with the pain of subversion.
Ok, I can get behind JFK's quote "We choose to go to the Moon not because it is easy, but because it is hard" - but do we have to apply the same quote to git? The way I see it, git is a tool and not a goal in and of itself. If there is a tool that does the same thing in an easier to use way (and can work with git repos), why use git? Of course, using VCS is part of the job description of almost every developer in the world, but git !== VCS...
"if some students fail the test, the problem is of the students, if many do, is of the teacher".
Git is a bad teacher. There are a lot of things that are profound yet easy to grasp when learned and other things are called bad products. Git is one of them.
> You MUST take the time to understand how it works properly.
Unfortunately, I agree.
It is both ubiquitous and so unnecessarily complex. The fact that all developers are required to memorize at least a few of its inscrutable incantations reflects poorly on the industry and on the judgement of its practitioners.
Are you writing everything in assembly? If not, your argument has no legs.
Moreover, you can use jj almost completely seamlessly with a git repo - including PRs etc to github. I do it daily and no one is the wiser.
I use a gui for 90% of my workflows. Another 9 percent points are hitting back in my console history to rerun commands, never mind if git or jj or POSIX that affect my working dir or index state.
What am I supposed to do, use the UI plus jj, and prompt an LLM to use which: git, or jj, in case I am too lazy to think of the right command in the remaining one percent of cases?
But in general, I like the "less states and DVCS features than git" approach, but would not switch back to mercurial just to avoid the whole "should we rebase or create merge-commits" discussions in our teams due to having a single default that might not be optimal for everyone, but just works.
use jjui - its an absolute pleasure to use as you dont need to know anything beyond arrow keys and some keyboard shortcuts (which you can also find in the ? help menu). https://github.com/idursun/jjui
If it doesnt do anything you already need, then the maintainer is likely to add it quickly - its rare to find someone so responsive
I feel like anyone who spends just a couple of hours learning git will have a much better mental model than the crappy "Assembly line" model from the article.
Your real mental model of git should be an acyclic directed graph where the nodes are commits and the edges are ancestry. Commits represents snapshot of the project's state. Tags and branches are just text pointers to commits in the graph.
If you use this mental model, suddenly things like git rebase or git reset become far less mysterious and arcane since they are just simple graph operations. Like `git reset --hard X` means "Make current branch's text pointer point to X"
I think the author is one of those folks who were able to fully grasp the beauty of the Git data model for the first time by switching to Jujutsu. It makes it easier to see the “DAG of commits” vision than Git with its index and stashes and confusingly named commands with fifty flags.
Yeah, exactly, and I've fruitlessly read too many guides on git's data model.
What was holding me back turned out to be the fact that git has too much magic (it updates branches automatically when you commit, rebasing "does stuff", conflict resolution was just arcane).
Jj exposes all that into simple, composable principles, making everything click.
> What was holding me back turned out to be the fact that git has too much magic
Considering jj is built on top of git, doesn't that mean jj has even more magic? That's like saying React is too magical so we should use Next.js instead (which is built on React).
Maybe you just mean that jj has a more intuitive CLI than git?
Jj uses git's data model, that doesn't mean it uses git commands for everything under the hood. Creating a commit with jj doesn't move the branch tag automatically, whereas git does. That's what confused me with git, it didn't expose the internals enough, so even though I had read about the data structures, it never clicked what was changed when, because git did it under the hood.
Which is why I always make sure to show that graph to co-workers new to git (we have a lot of code still on svn):
I keep it as an alias, but it is annoying that seeing the whole structure is so hidden away.Isn't this the same graph, that every Git GUI program shows?
I understand git at a pretty deep level. I still very much prefer jujutsu. Its rebase is just so much more powerful than git. I regularly work on top of octopus merges in jj of all my in-review parallel PRs and when I want to rebase them all and the octopus merge and the various anonymous branches on top it takes 1 command. It’s so much more powerful than git it’s crazy.
Totally agree on the DAG point of view, but I would argue that for different people you need different analogies/models to make it click. I would argue that pointing towards graph theory might help people that have a formal CS or maths education, but not necessarily folks that went through bootcamps, switched from design roles, have a biology background (e.g. bioinformatics) or do statistics (e.g. in medicine or psychology)
In the age of Claude Code and other MCPs, the last thing I want is my commit history to be mutable. I've added instructions to Claude which make a commit before each modification with a summary of the conversation that caused the change. Once I'm happy with the work, I squash the commits and push up. (Which I believe is more or less equivalent to the jj workflow.)
This flow can work with jj also. It would probably be exactly the same. You'd do `jj new` and have Claude set the description and make its changes. When you're ready for the next round, you'd repeat and do `jj new` again for the next revision.
I think jj's mutable revisions are best thought of as automation around `git commit --amend && rebase_everything_after_this_commit`. If you're not using that kind of flow with Claude, you wouldn't use that kind of flow with jj either.
Anyone using `jj`, how well does it scale?
I routinely use .git folders that are 11GB (+4GB checked out files) and 10k+ branches without issue.
My data point is the Mozilla monorepo. My .git directory is 5.5GB, so half of what you're talking about. jj speed has not been a problem at all. Some thing are sped up a bit by enabling watchman, but I didn't bother for the first 4 months or so that I used it because the speed was already fine and I didn't want to add another point of failure. (And in fact, when I first enabled it, it slowed things down because the checkout is too big and hit inotify limits.)
I don't have very many branches, though. 13 branches, 6838 tags.
Some caveats: jj's version of `blame` (jj file annotate) is painfully slow and I usually run `git blame` instead. (Which is a general thing: if anything is missing or slow, you can always just do it with git.) jj's rebase is insanely fast -- especially if you add in the time to manually resolve conflicts, since a good chunk of the time I don't have to spend any time at all since the conflicts are only in experimental twigs that I may never need to go back to (and if I do, it's fine to wait until I need it).
I have primarily used git in the terminal for more than a decade. I also used magit when I was primarily working in emacs (magit's great!). I now primarily use lazygit. While I'm not a fan of the whole UI, this is the only git tool that makes me go super fast while creating a near-perfect commit history. I tried using jj but immediately stopped after installation as it required a learning curve that I wasn't ready to commit to yet.
you might consider trying again, but do so with jjui (https://github.com/idursun/jjui) - very similar concept to lazygit and makes working with (the already simple) jj even more seamless and intuitive
thanks!
I don't really understand the appeal of jj as someone who uses sublime merge [0]. It has good support for submodules, a lot of the editing commits (messages, squash, move etc...) is really easy and I can also see and edit my stashes directly. Is there any benefit to jj compared to this?
[0] https://www.sublimemerge.com/
committable conflicts give you painless rebases. if you know about rerere, try jj; if you don't, it might not be worth it.
Until jj supports `git rebase -x "cargo check --deny warnings"`, it's useless to me. jj has primitive support for fixing individual files that changed, but it cannot work on any linter or formatter that depends on other files.
When checking out means to just "reopen" an older commit, how do you checkout single files in JJ?
Depends on what you mean. "Checking out" is ambiguous, and in fact isn't jj terminology. As git terminology, it could mean switching branches or showing file contents or going to a detached HEAD or resetting file contents.
If you want the contents of the file at some old commit 0a123, `jj file show -r 0a123 <filename>`. If you want to overwrite the current version of a file with the version from 0a123, `jj restore --from 0a123 <filename>`.
How do you "checkout single files" in git? What does that mean?
> How do you "checkout single files" in git? What does that mean?
So the answer is jj restore. Thanks.Checkout means that the version of some files at some commit is "checked out" in the worktree. So all these things are mostly the same in Git terms. The arbitrary split into switch and restore is confusing to me.
I don’t get it. Git is working well enough. Any failure on git workflows is usually failure in team process.
The article reads like you can’t change local git history before pushing. I do that all the time.
it's hard to take the article seriously when the author relies on a fuckgit alias on a regular basis
git rebase|cherry-pick|revert --abort and git reflog can solve pretty much all of my problems with git repos in weird states, and any advanced Git user should know them.
what im most impressed by when I read the comments to jj-related threads is how many people are handwriting assembly code.
I come to this conclusion because there's always a large amount of people saying "if you dont understand, let alone have mastered, git, then you dont get to have an opinion"
So, clearly these people similarly dont use ease-of-use abstractions like programming languages
"Git is too hard" is never a good argument to promote the use of a different tool. I use git on the terminal exclusively, never had an issue amending a commit or rebasing a branch, or even dealing with conflict resolution most of the time I just use one of the automatic strategies.
> "Git is too hard" is never a good argument to promote the use of a different tool.
Really? Pointing out that a tool is difficult to use seems like an excellent argument to promote the use of a different (supposedly simpler) tool.
Specifically in the case of git, I'm glad it was not difficult for you, but it is undeniable that it is a very difficult tool for many people to learn.
one of the better jj writeups. People, just TRY it out.
Weird cultish vibes I'm getting, especially the "i just dont get git" part. Shows that you did no research.