jj init – getting serious about replacing Git with Jujutsu
v5.chriskrycho.com
v5.chriskrycho.com
So I clicked on this link with the hope that it might be a kinder, simpler VCS. Especially after the article author talked about how bad Git's CLI is and how much better Jujutsu's is. But it looks like it's just as much of an overcomplicated clusterfuck, and since it's built on top of Git, you still get to experience all the pain of Git if anything goes wrong. And I wonder what kind of frightening scenario occurs when some contributors use Jujutsu and some use Git.
I understand that Git is powerful, and many of its features are valuable for large teams working on enormous projects (like the Linux kernel it was invented to manage). Hardly anyone needs that, though. I want a dead simple VCS for small project use that doesn't come with so many footguns. I know simpler VCS exists, but without wide adoption, GitHub-like repos, and tooling support, using Git is still the path of least resistance.
Last thing we want is a kinder, simpler, dumber VCS replacing git, like microframeworks which hardly have HTTP routing and middleware replaced full featured frameworks.
I think this illustrates a bit the tragedy of git's (lack of) UI. Since the reflog is a feature, not an exposed hidden internal. It's simply a log of what a reference, say HEAD, or a branch, has pointed at. It's meant to help you figure out what happened, or get back to a place you lost through some other operation.
I've used CVS, SVN, hg, bzr, and git. Why does git stand alone as the only VCS where devs need so many foot bandages?
I said typically though. We all know the “you move an image in Word and your layout completely changes” meme. Sometimes someone wants to undo something because the tool didn’t do what they intended. Even though I have no empirical basis beyond my no experience, I am incredibly confident that the typical use of Undo in a word processor is because the operator has changed their mind about what they want their output to be, rather than because they had already concluded what they want the end result to be and they just can’t get the software to do it. I have to imagine that you agree with this.
So yes, be thankful that git has reflog. All other things equal, git with reflog is better than git without. I don’t see how your analogy invalidates or refutes the the critique that typical use of git’s reflog is as a result of the operator not knowing how to use git. And to simply say “you’re holding it wrong”, when ‘holding’ git routinely involves standing due East at the next full moon, is absurd.
I’m not saying git has a great user interface that users intuitively grok and rarely make mistakes in. But I am saying that having an undo button is not an admission of that, either.
If you use the undo button because your word processor doesn't do what you want a lot, maybe look for a word processor that's better designed.
hg has similar thing but it's different for each command. For example to undo "hg strip" you manually dig into .hg/strip-backups directory.. I never understand why people call it more intuitive.
Can't tell you anything about bzr, never used it.
I could answer, but I don't think you're actually asking for someone to explain it to you.
I did want to offer a different opinion though. I like detached heads, they are unnamed branches, the first thing I do when working on something new is make a detached head and get to work, making commits, etc, if I decide the work is worth keeping, then I will name the branch. As some smart people have said, naming things is hard, I don't want to name a branch before I'm sure what it is or that I'm going to keep it. Having a bunch of commits that are not part of a branch might sound risky, but not if you understand that commits are never deleted (unless there 90 days old or more) and the reflog and other tools allow you to find commits you thought might be lost. Git does not lose commits, not ever.
But git names are not permanent, so just use whatever helps you remember: "just-ate-tuna-sandwich", "fifth-time-is-a-charm", "john-is-late", "idea-from-restroom", even "temp123"...
You can always rename to something that makes sense later.
git commit -am “Dead-end: I tried doing X but that didn’t work out”
git branch deadend/tried-doing-x
git reset —-hard HEAD^
I like this because, fully half the time I end up needing to draw some elements from that dead-end if it turns out later to have seeds of the right approach in it.`git branch <something-temporary>` is an absolutely fantastic workflow IMO, combined with committing early-and-often, it helps me decide on logical names for various snapshots of where I was when trying to solve a problem. When I hear people say “squashing is wrong” I can never understand what they’re on about: being able to make temporary semi-meaningful commits and branches on your way to the right answer to a problem, is an absolute godsend.
So yeah not only is the detached head state not a broken state, it's not even really a scary state to be in.
Good naming is hard, but you don't need those for your use case of potentially discardable work
That way a 1000 line pr consisting of 25 commits can be landed as 5 dependant prs with a much more focused review.
A few hours on https://learngitbranching.js.org/ and it'll make sense to you.
Imo it is some internal objection (due to hate? laziness?) to deal with it.
Yes, the UI is not intuitive in all parts and partly ugly or from some viewpoints inconsistent, but that lately improved much. Nevertheless, complex is different. Much more effort went into mastering chosen shell, much more unintuitive is the IDE I have to use.. but those are tools, and that's my job.
> WTF is "detached HEAD"? I've looked it up dozens of times, and as soon as I get past whatever I'm working on, I forget what it means.
Don't wanna be mean, but again I wonder how you learn and handle e.g. complex data structures (vs that super simple thing..) or other hard problems in whatever you do.
> And on any team I've ever worked on, the branch history is a nightmare to look at.
Because teams have many people that don't care. I like git, shuffle commits around, rebase easily, conflicts are easy to resolve (there are merge tools that exist to help on top?) or would be hard with any other tool the same? (need to try jj). At least I have seen same shit happen with cvs, svn and also the short time I used hg - people are always at fight with their version control, I don't know why. I'm glad if there is a new tool that finally solves this, buut, I doubt it ;) Let's see.
> I want a dead simple VCS for small project use that doesn't come with so many footguns. I know simpler VCS exists, but without wide
Sorry, but lame excuse, just chose and try one and see, don't spread that much git-hate if you have not even tried, and mastered, another one? (And here you are with jj!)
I'd bet within the past week you were swearing at git. :-)
I've written parsers and compilers, worked on image processing software for the NASA Mars rovers, managed global Kubernetes deployments for Fortune 500 companies, wrote trading desk software used on the NYSE trading floor, etc. Point being, I've worked on some seriously complex software. I'm 100% sure I could write Git itself without any trouble whatsoever (assuming I learned how it worked first).
I find Git to be unintuitive and overly-complex, and to use terminology that isn't obvious. You're probably right about it being an internal objection, but I assure you it's not due to laziness or an inability to deal with complexity. I'm not planning to use jj, because it's just Git with more complexity layered on top, despite their claims to the contrary.
Despite my dislike of Git, I'm still the go-to person for Git issues on the teams I manage. I can fix problems that arise and help others do things right. I still don't like it, and for whatever reason, the edge case scenarios don't stick in my memory.
is it my age? (i learned working with computers in the late 80s.)
the fact that i first had to work with CVS and subversion?
that i was an early adopter? (i was the first to use git at my job at the time, thanks to its good subversion integration)
have i just not seen how much better git could be? (am i happy with git out of lack of experience with better tools?)
or am i just different? (i seem to have no problem with weird programming languages or frameworks either (although there was this one perl job where i did struggle and ultimately had to give up because i had no help))
I mean, I personally geek out over the details, but let's be real: most folks, especially those not in software development, don't work like that. Even for us developers, you don't need to know the nitty-gritty of machine code to whip up some Python scripts. Sure, some of us love diving into that stuff, but it definitely shouldn't be a must.
Let's stop making excuses for mediocrity.
P.S. > “developers_, people who are, ostensibly, computer experts”
It’s laughable to me that people have this impression. It’s extremely rare to find a developer who has any knowledge at all on how to do basic computer things like installing an operating system, troubleshooting a network, understanding DNS, or being able to do anything outside of their programming environment.
> Do you expect that everyone who uses a database should know all the internals of the data structures stored on disk, journals, ram cache, etc. before they try to do basic SQL?
Honestly? Yes. Knowing the basic data structures stored on disk helps you understand why having an index is important, and just creating tables and doing queries on them is going to lead to extremely slow queries. Understanding journals helps you understand transaction isolation levels, which helps you understand why you can’t just have N web workers all doing write queries at the same time and they don’t necessarily see each other’s writes right away if they haven’t committed a transaction. RAM cache helps you understand why journaling is important in the first place if the database crashes.
I absolutely do believe that anyone who calls themselves a professional should be armed with such understanding before they go writing SQL code in a production context. Playing with it as a toy in your spare time? Go nuts, learn in any order you want. But if you’re writing code for an app that we’re shipping to users and that your coworkers’ livelihood depends on, you should get the friggin’ basics down.
> It’s laughable to me that people have this impression. It’s extremely rare to find a developer who has any knowledge at all on how to do basic computer things like installing an operating system, troubleshooting a network, understanding DNS, or being able to do anything outside of their programming environment.
I agree with you, but I would frame this as a lament. It really fucking sucks that my coworkers sometimes show now desire whatsoever to understand why their code doesn’t work on a machine with IPv6 enabled. Or don’t bother to care about why their ABI-breaking change caused missing symbol errors when downstream clients tried to run against the new build. You want my opinion? These people should leave the industry, and we’d be better off.
This is why we have buffer overflows...
This isn’t quite a right. I hope my clarification is helpful!
HEAD is the ref that you currently have checked out. This could be a commit ID, a branch ID, etc., and there may be multiple refs that point to the same commit.
When you check out a commit ID directly, you’re in a “detached HEAD” state because you aren’t on a branch. This is noteworthy because it means that any commits you make will be untracked by any branch, and will only be available in the reflog.
I also use `jj` without anyone else knowing. I get to smile a relieved smile when coworkers talk about making mistakes with git rebase/reset -f/stash. I don't sweat stacked patch sets. I never, ever, ever lose work. Ever. Never. Not even in my worst fat-finger, because of the oplog.
It's really good. Please form your own opinion from trying it. I also find the article a bit too lengthy to easily digest.
I'd imagine a binary that replaces git commands with other, saner ones, will do 95% of the work, while retaining compatibility with both past repos and the whole world wanting to use git.
Is the publicly available version of Sapling usable? I really miss stacked diffs every time I'm working on a GitHub project. Last I checked it seemed there were some dependencies on Mononoke and EdenFS which are not open source.
Yes — I've been using it as a Git replacement for a few months now. A little rough around the edges but mostly it just feels like a better Git to me.
Of course if there is an algorithm at some point, it would be really cool to see it described somewhere.
By the time I got to the changes section I was a bit too tired to keep reading.
I also read a ton of paragraphs excited about an easier Git, but I just couldn't understand what you were talking about and how it make my life easier. What does it mean to make merge conflicts first class?
BTW jj's documentation does a better job explaining what's the revs and changes are.
My only grudge with jj's CLI it uses `-r` to specify first class entities. Git here does rare proper thing and uses positional args for commits and ranges.
I can't afford to invest in Google's soon-to-be-abandonware projects.
Where is upstream?
In theory, this is not an advantage of the idea of the index, but simply a consequence of the fact that no GUIs have yet been written with jj in mind.
In practice, this can be a real limitation of jj for people who are used to such GUIs, for now.
I happen two think that two steps are better. If every new and changed file is automatically included in the next commit this will just lead to more devs not caring about properly splitting up changes into logical and related commits. Just commit everything in a single commit, push, home time! For those people the two step process seems a needless waste. For me it's to encourage devs to only add related changes into a single commit.
>this will just lead to more devs not caring about properly splitting up changes
I strongly disagree. jj split reduces the friction in splitting commits. Just think what you have to do to split a commit with git following your 2 step guidance. git reset HEAD~ && git add -p commit && git add -A && git commit. It's even worse for jj split -r @-- (split the 2nd to last commit (ignoring your working commit)). For git you have to do git rebase -i HEAD~2 && git add -p commit && git add -A && git commit && git rebase --continue. In the interactive rebase ui you select the 2nd to last commit to be edited. People avoid splitting with git because there is too much friction. It takes too many commands. It's hard to remember. You can screw up and waste even more time. If you want to encourage devs to split up commits then make it easy to do.
Jujutsu is the topic of this comment section and in Jujutsu all changes are always part of a commit, so splitting commits is the only way to separate changes into their own commits. And yes, with git I have wanted to retroactively split commits apart too. I don't always get everything perfect on the first try and may want to move certain changes from one commit to another.
Thank you for explaining again why I prefer git.
Correct. Lots of alternative git frontends drop the index and force you to include all changes in the commit, because they think users find the concept of staged vs unstaged changes confusing. This one doesn't.
That isn't accurate. Jujutsu doesn't even let you have untracked, working, or staged changes as everything is always committed (except for what's in .gitignore). Any change you make will be forced to be part of your current commit.
Certainly when I split a change up in git or hg, I’m usually trying to break off a piece that goes before the rest. TortoiseHG’s committer works like that — you select the parts to commit, and the rest stays uncommitted in the working copy.
So maybe the only tooling needed to make jj better is a mode (or maybe a default) that reverses the initial guess as to which parts of the change go where.
Except…when you’re actually splitting an existing commit with interactive rebase, don’t Git tools make you unstage changes that should go second? I see how it’s backwards and annoying compared to “git add -p” for a new commit, but they seem equally bad for splitting existing ones.
I plan to return to my experiment sometime, would love tips on large repos and making it more manageable.
[1]: https://www.mgaudet.ca/technical/2023/11/23/exploring-jujits...
Maybe it has some support for this already since it apparently works with Google’s internal monorepo? I can’t tell what the story there is.
You also lost me a bit on “change”. What is a change? If I modify a change, does it keep the same id? What if I send you a change and then modify it? At what point are changes immutable? What if I end up with two changes with the same id that aren’t the same change in my repo? The asciinema casts might have helped a bit, but the lack of scrolling or an easy scrubber makes it really hard to follow.
Very True.
This whole article really makes me miss mercurial. No need to create branches all the time, very rarely needing rebase -i, revsets, simple commands, those were the days! I'm almost afraid to give jj a try because I'll fall in love and probably lose it again and have to go back to git
Talks about how it uses revisions not commits or something, but never really explains why it's good, just more that it's different to git.
So I think this is probably a very good article for someone who actually knows git, but isn't very good for the users he says would most benefit from it!
I'm using `git gui` a lot, I think about everydays, to pick up exact what I want to commit or amend my current work. It's not a very fancy tool, but it ships with git by default and I feel it's really underused and could actually make people's life easier for editing undergoing work...
Detached HEAD and all, it's not that complicated to use.
When you come up with a replacement for javascript, then I'll be interestted...
Jujutsu is a very meaningful and good name for VCS.
The correct way to read it seems to be Jujutsu (柔術), not Jujutsu (呪術).
Please shoot me a Koku-Senn(黒閃).