Jujustu - A git-compatible version control system
In my previous job I used a (paid subscription) git GUI and so rarely resorted to using git via the command line. At my new job though there isn't a standard way to use git and most of the other devs just use the terminal. Because starting a new job in a new framework in a new city apparently wasn't challenging enough, I decided to also start using a new version control system as well. Enter Jujutsu[↗].
What is Jujutsu?
Jujutsu (or jj) is a version control system that 'colocates' with git. This means it has it's own (gitignored) folder in your project, records changes itself and works independently as a VCS. However, it can also be used in conjunction with git, making it very easy to try out and also use on projects where not everyone is using it.
Why use it?
My interest in this new VCS was piqued by comments on Hacker News praising it for being far easier to understand than git. I had always specifically avoided using git in the CLI for this reason - other than branches and commits (and the occasional rebase), most of git remains a black box to me.
More than once I've accidentally rebased incorrectly and borked my whole branch, only to have to scrap it and recreate it to rescue the situation. Jujutsu makes it easy to avoid this situation and, more importantly, makes it simple to resolve it just in case.
So how does it work?
Revisions
Unlike git, jj doesn't use branches or a staging area. Every set of changes you make in your project is automatically recorded as a revision1. Each revision has a unique ID and can be referenced in many jj commands. For instance, the jj new [revision] command is used to create a new empty revision on top of a currently existing one. This is the primary way of creating new 'branches' in Jujutsu. This workflow allows for easy switching between different versions of your code and the lack of staging area means no stashing and applying when you quickly want to checkout something else. To see all of the current revisions in your project you can run jj log. jj st will also show you the status of the current working copy revision.
Bookmarks
Instead of branches Jujutsu uses 'bookmarks', which are essentially tags on certain revisions. They are therefore not fixed to specific commits or parents or children of commits but can instead be moved around to whichever revision you decide represents the definitive version of your new code. This creates a simple flexibility that allows quick proof of concepts or bug fix attempts, without having to stay working within the same branch and commit chain, or creating stashes.
When combined with git however, a bookmark will be turned into a traditional branch on whichever commit your decide to push.
Rebasing
Rebasing with jj is also much simpler. Imagine you have a situation like this:
o abc A commit message my-branch
|
o def
|
o ghi
\ o mno master
\ /
o jkl
Now your branch (my-branch) is finished and ready to be reviewed. First you want to rebase it onto master to make sure the rest of the code is up to date. You do a quick jj rebase -s ghi -d master. But uh oh! Someone was working on the same files as you and now you have... Merge conflicts! woman screams
Your tree will now look like this:
o abc A commit message my-branch (conflict)
|
o def (conflict)
|
o ghi (conflict)
|
o mno master
|
o jkl
With Jujutsu this is not a big problem and the program itself will even tell you the steps you need to take to fix it. The first thing to do is to jj new to the first conflicted revision. In our case this is jj new ghi. From here you can fix the conflicts with Jujutsu's own jj resolve command, or like me in your IDE. The conflicts will only include conflicted lines and files from the current revision, making solving them a lot easier and quicker. Mostly you'll only have to fix one or two files. Once they're solved, the changes will be propagated to the descendant revisions, meaning you won't end up fixing the same issue more than once.
Now run jj squash to merge the fixes into the current revision. The tree then looks like this:
o abc A commit message my-branch (conflict)
|
o def (conflict)
|
o ghi
|
o mno master
|
o jkl
The next step is of course, jj new def and fix the conflicts again. This time only the conflicts created by revision def will need fixing. If there weren't any changes made in revisions def or abc that conflicted with master then both of them would also no longer be conflicted after we fixed and squashed ghi.
After doing it a few times the whole process becomes second nature and far less mentally taxing than rebasing in git. Very rarely have I ever had a jj rebase take longer than a minute to fix, but should anything really go wrong, Jujutsu has one more magic trick up it's sleeve.
The operation log
Alongside the usual log of revisions we can check using jj log, Jujutsu also keeps a separate log of actions we've taken. Each action gets it's own unique ID and is basically a snapshot of our project at the time the jj command was run.
If we do a complicated rebase and screw everything up (we've all been there), Jujutsu has 2 options to save us. The first is jj undo. This reverts the last operation, which is often enough if you want to undo a bookmark move or an accidental commit. The other option is looking into the op log, grabbing the ID of the operation before our mistake and running jj op restore [ID]. This will revert our entire project, and Jujutsu itself, back to the state it was when that command was run, essentially wiping away everything that went wrong. No one even has to know you messed up!
My experience
I've really enjoyed using Jujutsu and to be honest I can't see myself going back to plain git. Although the general differences between the two aren't huge, and the way I view Jujutsu is probably still through the lens of someone who learnt version control through git, I appreciate all the work the creators have done to improve VCS DX. Not to mention the huge benefit of Jujutsu being git-compatible, effectively circumventing the problem of trying to get everyone on board. I recommend at least giving it a try.
Links
If you want to check out Jujutsu (pun intended), you can find the GitHub repo here[↗]. You can also take a look at the documentation[↗] or read this far better blog post about it[↗].
Once you've got the hang of the Jujutsu basics, I also recommend jjui[↗] which does a great job of streamlining the most used jj commands into a user-friendly TUI.
Revisions don't actually have to have any content. Initially revisions are empty and have no description, but they still have an ID.↩