jj vs. git vs. GUIs
Published by marco on
The article jj init — Sympolymathesy by Chris Krycho explains what Jujutsu is and what it does. I was reminded of these notes that I wrote over a year ago when I read Evolving Git for the next decade by Joe Brockmeier (LWM.Net), which briefly mentioned it as a command-line UX toward which Git itself is working.[1]
Git is not worse than all the others
“Jujutsu is two things: It is a new front-end to Git. This is by far the less interesting of the two things, but in practice it is a substantial part of the experience of using the tool today. In this regard, it sits in the same notional space as something like gitoxide. Jujutsu’sjjis far more usable for day to day work than gitoxide’sgixandeinso far, though, and it also has very different aims. That takes us to: It is a new design for distributed version control. This is by far the more interesting part. In particular, Jujutsu brings to the table a few key concepts — none of which are themselves novel, but the combination of which is really nice to use in practice: Changes are distinct from revisions: an idea borrowed from Mercurial, but quite different from Git’s model. Conflicts are first-class items: an idea borrowed from Pijul and Darcs. The user interface is not only reasonable but actually really good: an idea borrowed from… literally every VCS other than Git.”
I don’t think that this is true. but I have perhaps more experience with “literally every VCS” than the author does. For example, Perforce changelists are anything but intuitive for new users. TFS and Subversion branches were a horror to deal with. Every feature of VSS was only tolerated because it was amazing to have source control at all.. It’s not just Git that has difficulties with UX.
The author is being a dick here, taking easy swipes that they know no-one will question. They just expect to get an amen from their chorus who think that, because there is room for improvement in the Git UX, that every other tool must be better. This is not true. But it doesn’t matter because Git can’t just be an amazing tool for which GUIs have filled the gaps in its UX: it has to suck in order for Jujutsu to save us all from it. People are tiring.
It’s a Google thing
“[…] given it is being actively developed at and by Google for use as a replacement for its current custom VCS setup, it seems like it has a good future ahead of it.”
That is such a naive thing to say, given the history of most of the software that comes out of Google. The best that you can hope for is that Google doesn’t try actively kill it while an open-source community tries to keep it alive.
Jujutsu’s features
“Jujutsu has two discrete operations:describeandnew.jj describelets you provide a descriptive message for any change.jj newstarts a new change. You can think ofgit commit –message “something I did”as being equivalent tojj describe –message “some I did” && jj new. This falls out of the fact thatjj describeandjj neware orthogonal, and much more capable thangit commitas a result.”
“[…] a given change logically the child of four other changes, with identifiersa,b,c, andd?jj new a b c d. That’s it. One neat consequence that falls out of this: a merge in Jujutsu is justjj newwith the requirement that it have at least two parents. (“At least two parents” because having multiple parents for a merge is not a special case as with Git’s “octopus” merges.)”
When would you need this? Am I missing a use case? I’ve never felt particularly like I needed to merge four branches together but I’m just a simple guy with simple needs. I’m sure I’m missing something by not wrangling four simultaneous branches instead of programming. Is this something that LLMs need maybe?
“[…] you can describe the change you are working on and then keep working on it . The act of describing the change is distinct from the act of “committing” and thus starting a new change. This falls out naturally from the fact that the working copy state is something you can operate on directly: akin to Git’s index, but without its many pitfalls.”
What pitfalls does Git’s index have? It seems pretty useful to me. At the end of the article, he actually backs off on this and admits that Git’s index is kinda necessary for staging parts of the workspace. Also, the whole feature—separating “describing” and “committing”—isn’t as revelatory as he’s making it out to be.
“Withjj new -A <some change ID>, you just insert the change directly into the history. Jujutsu will rebase every child in the history, including any merges if necessary; it “just works”. That does not guarantee you will not have conflicts, of course,”
Um. Ok. I mean, how could it possibly have guaranteed that? It’s not magic. Conflicts are the nasty part, though, and are always more difficult to deal with when doing operations on multiple commits at once.
Delaying conflict-resolution is cool
“Jujutsu can incorporate both the merge and its resolution (whether manual or automatic) directly into commit history. Just having the conflicts in history does not seem that weird. “Okay, you committed the text conflict markers from git, neat.” But: having the conflict and its resolution in history, especially when Jujutsu figured out how to do that resolution for you, as part of a rebase operation? That is just plain wild .”
I kind of like the idea of committing conflicts instead of forcing the user to resolve them immediately. That’s a good idea. It lets you revisit the merge by preserving the inputs.
“Jujutsu will add conflict markers to a file, not unlike those Git adds in merge conflicts. However, unlike Git, those are not just markers in a file. They are part of a system which understands what conflicts are semantically, and therefore also what resolving a conflict is semantically. This not only produces nice automatic outcomes like the one I described with my library above; it also means that you have more options for how to accomplish a resolution, and for how to treat a conflict. Git trains you to see a conflict between two branches as a problem. It requires you to solve that problem before moving on. Jujutsu allows you to treat a conflict as a problem which [must eventually] be resolved,”
“Jujutsu allows you to create a merge, leave the conflict in place, and then introduce a resolution in the next commit, telling the whole story with your change history.”
“Conflicts are inevitable when you have enough people working on a repository. Honestly: conflicts happen when I am working alone in a repository, as suggested by my anecdote above. Having this ability to keep working with the repository even in a conflicted state, as well as to resolve the conflicts in a more interactive and iterative way is something I now find difficult to live without.”
The article discusses retaining conflicts in commits as first-class, semantically valuable artifacts that the conflict resolver can either resolve immediately or later when another commit comes along to make the conflict go away. This is very interesting for multi-commit rebases where git currently makes you resolve the conflicts every step of the way, even when you know that the conflict will definitely go away further up the chain.
Often, you don’t even remember how you actually want to resolve the conflict in the “old” commits—and you don’t care. This only happens with rebase, which I use much, much, much more than merge. When you merge, git considers the sum of all changes in all commits that you’re merging, so you get the behavior you want: the sum of the commits eliminate irrelevant conflicts. Rebase in git doesn’t benefit from this behavior. In jujutsu, it does.
Massaging your commits is good, too
“[…] this ability to move part of one change into a different change is a really useful thing to be able to do in general. I find it particularly handy when building up a set of changes where I want each one to be coherent — say, for the sake of having a commit history which is easy for others to review.”
Yes, of course. Some of us have just been using powerful GUIs to do this for a long time, with hotkeys flying, instead of furiously typing commands into a command line. This is a laudable goal. I’m glad that jujutsu brings that experience—and that ability—to command-line users.
Wait. No branch names?
“The default log template shows me the current set of branches, and their commit messages are usually sufficiently informative that I do not need anything else.”
Sure, ok. No branch label required. That’s definitely not a recipe for disaster for most developers. It never struck me as too burdensome to have to make little bookmarks, really. It felt kind of obvious and logical. I guess I didn’t notice that I was wasting time when I could have just been reading commit messages instead.
Acknowledging Git GUIs
“GUI tools could make all of those much easier. Any number of the Git GUI s have tried, but Git’s underlying model simply makes it clunky. That does not have to be the case with Jujutsu. Likewise, surfacing things like Jujutsu’s operation and change evolution logs should be much easier than surfacing the Git reflog, and provide easier ways to recover lost work or simply to change one’s mind.”
First of all, I don’t think there’s that strong a point to make here. A GUI like SmartGit manages to elide a lot of the complexity and has done so for years.
I wonder if Syntevo is working on anything for jj? Or is there no point because SmartGit has actually already been doing what Jujutsu does for a while? Maybe there is an advantage to storing the conflicts that SmartGit could also leverage.
Editing history for code you don’t have checked out
The article I’m daily driving Jujutsu, and maybe you should too by Drew Devault writes,
“As a git power user, I rely heavily ongit rebaseto edit my git history as I work, frequently squashing and splitting and editing commits as I work, and I used “stacked diffs” without branches before it was cool.”
Same. I’ve just never done it on the command-line, so I’ve never felt the pain of doing any of this git-fu there. SmartGit makes most of my history-editing seamless, easy, and foolproof. I know all of you console-jockeys hate them but give me drag-and-drop operations any day.
“When I edited this earlier commit, I was in the middle of working on something else and I hadn’t committed or even staged it. I did not run
git stash, norgit commit -m”WIP”, norgit add, norgit checkout, norgit rebase, at any point. The only command I ran wasjj squash. When it was done, I was returned immediately to where I left off, with a half-written, uncommitted change in my workdir. It took all of two seconds to complete this operation and pick up where I left off.“The “wow” moment came when I realized that I had done this several times that day without finding it particularly remarkable. Jujutsu makes editing history absolutely effortless.”
This is, I think, the killer feature of jujutsu: you can edit history that you don’t currently have checked out.
While better conflict-handling and editing commits anywhere in the tree are attractive features, I still feel that switching back to using the command-line would incur enough drawbacks to outweigh the benefits for me.
Jujutsu Kaisen is a completely unrelated anime
That article wrote,
↩“There are a number of things that Jujutsu got right, he said. For example, history is malleable by default. “It’s almost as if you were permanently in an interactive rebase mode, but without all the confusing parts.” When history is rewritten in Jujutsu all dependents update automatically “so if you added a commit, all children are rebased automatically”. Conflicts are data, not emergencies. “You can commit them and resolve them at any later point in time.” These features are nice to have, he said, and fundamentally change how users think about commits. “You stop treating them as precious artifacts and rather start treating them as drafts that you can freely edit”.”