What I like about Jujutsu
Recently I’ve been using Jujutsu for a while. It’s a Git-compatible VCS that is both simple and powerful.
I’ve been using it for a while now, and I’ve grown to like it a lot. I wasn’t convinced at first, even now I’m having a hard time explaining to people why I like using it over a plain Git client. On a surface level it doesn’t look as appealing, it’s one of those things that you can only feel the benefit of after using it for a while, at least that’s how I feel anyway.
Some disclaimers, this post is not a tutorial on how to use Jujutsu since the docs cover those well enough and there’s too much to cover (also because I’m too lazy to write them up :p). These are just some of the things I like about Jujutsu that made my development workflow much better and hopefully you understand Jujutsu a bit better.
Why Jujutsu
Jujutsu emphasizes simplicity while still being powerful. The simplicity is what actually enables it to be so powerful yet so easy and intuitive to use. It picks inspirations from some of the most used version control systems out there.
You can check their feature highlights in their README but for me it all boils down to “Git if it was written today”. A lot of the design just makes more sense to me, and being Git-compatible it’s super easy to adapt to existing repositories. The fact that Jujutsu assumes everything is a draft until you push to a remote resonates with me who’s a bit messy when working. It enables me to have a clean history.
I actually didn’t have any strong reasons to switch to Jujutsu but I just happen to like to try new things, and people have been talking about it on Twitter, so that got me curious. I looked through their docs, watched some videos about it, and to be honest I still wasn’t convinced at first. I thought it’s just Git with a slightly different workflow, and boi was I wrong.
Revisions are GOATed
When using Git, the flow I usually follow when working on something and want to create a commit is this:
- Make some changes
- Stage the changes
- Commit the changes with a message
- Push the changes to the remote repository
- Repeat
This is a very simple flow, you make changes and then you commit the changes like you’re saving progress.
In Jujutsu, you don’t have a staging area, everything is automatically snapshotted whenever you save a file automatically. It gives me the flexibility to move around between
- Describe the changes on the current
revision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. - Make some changes
- Make a new
revision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. - Push to remote if satisfied, or repeat step 1-3 and move around between revisions
It’s a lot more flexible and allows me to play around with the history, especially when I use AI. I can just create a new
The big difference here is that
This flow also enables Stacked Diffs because it relies on the ability to cascade changes, and Jujutsu supports that by default. I don’t have to fiddle around with rebasing and whatnot, it does that for me automatically.
There’s no more detached HEAD state because you can just move around between
Branches Made Simple
There’s no concept of branch in Jujutsu, it’s all just
You don’t have to worry about checking out to a branch, you just bookmark your revision and move to it. Moving between branches is literally the same as moving between
One gotcha you might not be used to if you’re used to Git is that you have to move the
I honestly have no idea how can I explain this better, you should really try it yourself and see the difference. It took a while for me to click, but once I do, I can never imagine myself moving to branch anymore.
No Need to Stash!
This is one of the biggest problems I’ve had with Git. Whenever I change between branches while working on something, I only have two options:
- Stash my changes, checkout to the branch, finish work, back to previous branch, pop the stash
- Commit my changes, checkout to the branch, finish work, back to previous branch
Sounds simple enough, but here’s the problem, I find myself switching between branches quite a lot, especially when there’s something urgent that needs to be fixed while I’m still working on something. I ended up having a bunch of different stashes under different names, messy!
Jujutsu solves this problem by removing one of Git’s feature, the
So the flow now looks like this:
- Work on
feat/new-stuff, we’ll call this revisionabc. - Something broke on prod, need a quick fix, create a new
revision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. fromstaging, we’ll call thisdef - Fix the issue, push to remote, be done with it.
- Continue working on
abc.
Since we don’t have a abc, and when I switch to def, none of those changes follow me, it’s like switching to an alternate timeline. After I’m done with everything, I just go back to abc and continue working.
This is why I think Jujutsu’s jj split which basically splits your revision into multiple ones. You just select which files you want to put on another jj squash.
To simplify things, Git wants you to commit your changes, once it’s committed then it’s done, it’s a commitment. In Jujutsu, however, revisions are like lego tree where you can move things around, change things here and there, it’s much more flexible when you want to have a clean history and experimenting with different things.
Time Travel
Messy Rebase
Imagine this, you’re working on a separate branch, you’re 12 commits ahead, it drifts so far off from the main branch. So, you thought, it’s time to catch up and rebase the main branch. As we all know, rebasing isn’t that easy if the code you’re updating overlaps with the other branch, which causes conflicts. You resolved 7 conflicts, you rebased 20 commits from the main branch, and you feel good… except, things went sideways. Now you’re left with a broken state of the repo, none of them works anymore.
After the rebase process exploded, you try to fix the issue by using git reflog, which is a chronological dump of every Git’s internal state transition that has happened. Here’s an example on how it looks:
8b3458d (HEAD -> feature/auth-fix) HEAD@{0}: rebase (finish): returning to refs/heads/feature/auth-fix
8b3458d (HEAD -> feature/auth-fix) HEAD@{1}: rebase (pick): feat: update src/api.ts feature-12
f4c02c2 HEAD@{2}: rebase (pick): feat: update src/utils.ts feature-11
ec84756 HEAD@{3}: rebase (pick): feat: update src/config.ts feature-10
2034d37 HEAD@{4}: rebase (pick): feat: update src/user.ts feature-9
d033fd7 HEAD@{5}: rebase (pick): feat: update src/auth.ts feature-8
46958a0 HEAD@{6}: rebase (pick): feat: update src/logger.ts feature-7
020fb29 HEAD@{7}: rebase (pick): feat: update src/db.ts feature-6
b2bdf3a HEAD@{8}: rebase (pick): feat: update src/api.ts feature-5
5ff5592 HEAD@{9}: rebase (pick): feat: update src/utils.ts feature-4
59c5aad HEAD@{10}: rebase (pick): feat: update src/config.ts feature-3
293e8e4 HEAD@{11}: rebase (pick): feat: update src/user.ts feature-2
dbc5cd2 HEAD@{12}: rebase (pick): feat: update src/auth.ts feature-1
3cfe6a9 (main) HEAD@{13}: rebase (start): checkout main
c1805f1 HEAD@{14}: commit: feat: update src/api.ts feature-12
If you look at the reflog, you’ll notice that there’s a lot of rebase commands. There’s also rebase (start) and rebase (finish), which is the marker for when the rebase has started and finished. There’s too many noise in this log, we don’t really care about all the details when we just want to go back to the previous state. Now you’re here looking for which HEAD contains the safe state of your app before the broken rebase.
Let's do a little quiz and see if you can recover from this :)
Which HEAD contains the safe state of your app before the broken rebase?
Congratulations if you got it right! In all fairness, it’s not that hard to begin with, there’s just a lot of noise that needs to be filtered out to get where we want. Alright, so now we know the HEAD that we wanted, the next step is to do git reset --hard HEAD@{N} right? A destructive command that permanently discards everything. Let’s just assume you get the number correct, problem solved, but what if you didn’t? What if you did a typo and you didn’t realise? What if you got the number wrong? Then you’re left with an incorrect reset, back to the broken state we go! Oh, and as a bonus, all of your unstaged files are gone.
Alright, alright, I know you can do the same thing again since Git keeps everything in the reflog. Technically you can keep doing git reset --hard HEAD@{N} to recover, but you’re back to figuring out which HEAD contains the state you want. This is because each time we do any operations, the state changes, and the number shifted, HEAD@14 now becomes HEAD@15 because there’s a new entry at the top from you doing a reset. See this new reflog after I tried to reset back to the incorrect HEAD, and finally reset to the correct state before the rebase.
c1805f1 (HEAD -> feature/auth-fix) HEAD@{0}: reset: moving to HEAD@{15}
3cfe6a9 (main) HEAD@{1}: reset: moving to HEAD@{13}
8b3458d HEAD@{2}: rebase (finish): returning to refs/heads/feature/auth-fix
8b3458d HEAD@{3}: rebase (pick): feat: update src/api.ts feature-12
f4c02c2 HEAD@{4}: rebase (pick): feat: update src/utils.ts feature-11
ec84756 HEAD@{5}: rebase (pick): feat: update src/config.ts feature-10
2034d37 HEAD@{6}: rebase (pick): feat: update src/user.ts feature-9
d033fd7 HEAD@{7}: rebase (pick): feat: update src/auth.ts feature-8
46958a0 HEAD@{8}: rebase (pick): feat: update src/logger.ts feature-7
020fb29 HEAD@{9}: rebase (pick): feat: update src/db.ts feature-6
b2bdf3a HEAD@{10}: rebase (pick): feat: update src/api.ts feature-5
5ff5592 HEAD@{11}: rebase (pick): feat: update src/utils.ts feature-4
59c5aad HEAD@{12}: rebase (pick): feat: update src/config.ts feature-3
293e8e4 HEAD@{13}: rebase (pick): feat: update src/user.ts feature-2
dbc5cd2 HEAD@{14}: rebase (pick): feat: update src/auth.ts feature-1
3cfe6a9 (main) HEAD@{15}: rebase (start): checkout main
c1805f1 (HEAD -> feature/auth-fix) HEAD@{16}: commit: feat: update src/api.ts feature-12
If you notice the first two entries, they’re both reset entries from me doing a git reset, but something looks odd. Look at the second entry, it says moving to HEAD@{13}, and if you look at HEAD@{13} it’s not even the correct state I was trying to go to. Now look at the first entry, I was trying to go to the actually correct state, which was HEAD@{15} but now it became HEAD@{16}! Just like I said earlier, the numbers have shifted, and now the history went out of sync. It has become a number puzzle game that’s very unintuitive.
I know it’s probably not that big of a deal for some people, but it’s just very annoying having to figure out all these numbers when all you want to do is just undo your last action. Also the fact that you have to rely on a destructive operation doesn’t sound great to me, we’re all bound to make some mistakes, it would be nice if there’s a safeguard that catches me.
Ol’ Trusty Ctrl+Z
In Jujutsu, you can just do jj undo to undo your last action, and you can undo the undo! Instead of reflog that shows all the internal state transitions, we have jj op log, which is more intuitive and more human readable. Take a look at this:
@ 10ecfb140a84 elianiva@melon 1 minute ago, lasted 81 milliseconds
│ rebase commit 06ac7f96a35a5f03bdbfbe9e4c8ec4a62cb331b4 and descendants
│ args: jj rebase -s feature/auth-fix -d main
○ 1061dd503e96 elianiva@melon 1 minute ago, lasted 44 milliseconds
│ describe commit b246ae11fda009bdcef1d60d2d2c90bf5969e448
│ args: jj describe -m 'rebase feature onto main'
○ 2ff05e708103 elianiva@melon 1 minute ago, lasted 45 milliseconds
│ new empty commit
│ args: jj new
○ 700c2942566a elianiva@melon 1 minute ago, lasted 9 milliseconds
│ point bookmark feature/auth-fix to commit 06ac7f96a35a5f03bdbfbe9e4c8ec4a62cb331b4
│ args: jj bookmark set feature/auth-fix
○ e433a0bd414e elianiva@melon 1 minute ago, lasted 49 milliseconds
│ new empty commit
│ args: jj new
○ 8a3afbb79105 elianiva@melon 1 minute ago, lasted 43 milliseconds
│ describe commit 540c9b2d334d884707e0e9fd40b9a2cec0740682
│ args: jj describe -m 'feat: update src/api.ts feature-12'
○ 31f2304af728 elianiva@melon 1 minute ago, lasted 41 milliseconds
│ snapshot working copy
│ args: jj describe -m 'feat: update src/api.ts feature-12'
○ 9461c4e14f1b elianiva@melon 1 minute ago, lasted 38 milliseconds
│ new empty commit
│ args: jj new
○ e10206d50112 elianiva@melon 1 minute ago, lasted 41 milliseconds
│ describe commit ccde03239baef8065f9026239814af8cefcee63f
│ args: jj describe -m 'feat: update src/utils.ts feature-11'
○ 2c60502f0aa4 elianiva@melon 1 minute ago, lasted 40 milliseconds
│ snapshot working copy
│ args: jj describe -m 'feat: update src/utils.ts feature-11'
As you can see, there’s a lot less noise in the log, and it’s much easier to find where the rebase happens. It is as if this history was designed for human to read! We actually don’t even need to see this at all if all we want to do is undo our previous operation, we can just run jj undo! The graph is useful if you want to undo certain operations because it groups all operations that has been done by the user instead of the verbose history like Git. See the difference when I tried to undo, but then I changed my mind so I undo the undo.
@ df5bed0d72ca elianiva@melon 22 seconds ago, lasted 8 milliseconds
│ redo: restore to operation 10ecfb140a849c8fd725c153abe8cfae630ab1d1137d4b56c469e93fd0924116483051a431d04df457ae1a40bc877381d099bcc2c22e52e7b022e24d846f227f
│ args: jj redo
○ 0d713cd1ce9f elianiva@melon 26 seconds ago, lasted 9 milliseconds
│ undo: restore to operation 1061dd503e96482fa0d9ab8371d18533653863292c763033fa5f54f944576410a1a3bc16aba7aafc9a73d707c02468c14f97ce1a127468803b05cca16b7e32fc
│ args: jj undo
○ 10ecfb140a84 elianiva@melon 1 minute ago, lasted 81 milliseconds
│ rebase commit 06ac7f96a35a5f03bdbfbe9e4c8ec4a62cb331b4 and descendants
│ args: jj rebase -s feature/auth-fix -d main
○ 1061dd503e96 elianiva@melon 1 minute ago, lasted 44 milliseconds
│ describe commit b246ae11fda009bdcef1d60d2d2c90bf5969e448
│ args: jj describe -m 'rebase feature onto main'
○ 2ff05e708103 elianiva@melon 1 minute ago, lasted 45 milliseconds
│ new empty commit
│ args: jj new
○ 700c2942566a elianiva@melon 1 minute ago, lasted 9 milliseconds
│ point bookmark feature/auth-fix to commit 06ac7f96a35a5f03bdbfbe9e4c8ec4a62cb331b4
│ args: jj bookmark set feature/auth-fix
○ e433a0bd414e elianiva@melon 1 minute ago, lasted 49 milliseconds
│ new empty commit
│ args: jj new
○ 8a3afbb79105 elianiva@melon 1 minute ago, lasted 43 milliseconds
│ describe commit 540c9b2d334d884707e0e9fd40b9a2cec0740682
│ args: jj describe -m 'feat: update src/api.ts feature-12'
○ 31f2304af728 elianiva@melon 1 minute ago, lasted 41 milliseconds
│ snapshot working copy
│ args: jj describe -m 'feat: update src/api.ts feature-12'
○ 9461c4e14f1b elianiva@melon 1 minute ago, lasted 38 milliseconds
│ new empty commit
│ args: jj new
As you can see, my first undo was restoring to the 1061dd503e96 state, which was describing the changes before executing rebase. this is the healthy state, I didn’t have to figure out which one is the right one because jj does that for me! The second undo I did was undoing the previous undo, basically a redo, which reverts me back to the 10ecfb140a84 state, that is the broken rebase. You can also see the exact command that I ran on the args: field. This lets you identify what command did you run quite easily, unlike Git which requires you to parse the state transitions and figure out the correct HEAD numbers.
From this alone we can see that Jujutsu is superior because it keeps a stable ID that doesn’t change no matter how many times we add operation entries. It also gives us convenient commands to help navigate forward and backward between states. It’s also safe! Remember how Jujutsu doesn’t have
It really feels like the design of Jujutsu treats recovery and experimentation as a first class rather than afterthought. This is so useful especially with coding agents these days where the cost of experimentation is getting cheaper and cheaper.
First-class Conflicts
I mentioned that Jujutsu feels like it treats recovery and experimentation as a first class. This can also be seen by how it handles conflicts. Jujutsu treats conflict as data while Git treats conflict as if the world has stopped and you HAVE to resolve it to make it continue running.
Since conflicts are just another data, you can just… commit them! This sounds odd when I first read about it, why would I want to commit conflicts, it breaks the code!!! That’s before I used it myself and realise how convenient it is.
I’m always annoyed whenever I catch up to the main branch and I see a conflict that I have to resolve, especially if I don’t really care about the conflicted file at the moment. Jujutsu enables me to just ignore it and continue with my work and resolve it later when I have the time. This mindset also enables collaborative resolution, you can just ask your mate (or coding agents!) to resolve them for you if you’re too busy dealing with a million of other things in the meantime, this isn’t possible with Git.
Remember how the rerere option, which is an opt-in behaviour in Git, but Jujutsu gives you this by default!
There’s nothing special about how Jujutsu stores conflicts, you can still see the <<<<<<< marker just like you would in Git, the code is indeed still broken, but the flexibility of when to resolve them is a big win for me. Especially when paired with coding agents, the speed of things changing are really quick compared with handwriting everything, so sometimes a single commit or change consists of a bunch of files changed, and some of them will bound to have some conflicts if you work with other people or spawning a bunch of agents in their own branch. The ability to just say ehh whatever I’ll solve this file later is great! It doesn’t stop your velocity of working on things, a single conflict on bun.lock shouldn’t require you to stop working and resolve it. You can simply ignore it, keep working, and resolve it when you’re done.
Powerful Query Language
Jujutsu has its own language to query the
My explanation won’t do any justice, you should read their docs to see its capabilities, it’s pretty cool!
Minor Incompatibilities
Since Jujutsu is still early compared to Git, we’re talking about 7 years old vs 21 years old software! There’s bound to be some minor imperfections here and there. These are some things that aren’t supported yet in Jujutsu but present in Git:
- No Sub-Module support, see this issue and this design docs for more information.
- No Git hooks support. They are planning on something similar using
jj run, see this design docs for more information. - …and probably some other things that I didn’t realise because I don’t use it.
Even though it has some gaps, I’m still very happy with Jujutsu. Its inconveniences aren’t big enough to ruin my workflow.
My Workflows
Here are some of my workflows that I’ve been using with Jujutsu so you know how I use it in practice.
-
Making regular commits
If I want to start working on something, I’d do
jj newto move me to a freshrevision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. , then I either work on thechanges In Jujutsu, changes represent your uncommitted modifications. Unlike Git's staging area, all changes are automatically tracked and snapshotted. , or I would dojj describe -m "some important message"to set the commit message. After I’m satisfied, I would dojj newagain, and the flow repeats. There’s no “commit” so you just move to the nextrevision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. . You can even edit thatrevision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. if you changed your mind about something as long as it hasn’t been pushed to remote, it’s a really flexible workflow. -
Making a branch
There’s no concept of branch in Jujutsu, it’s all just
bookmarks Bookmarks are Jujutsu's equivalent of Git branches. They're named pointers to revisions that move when you create new descendants. , so whenever I want to make a branch, instead of having to create the branch ahead of time before I change anything, I can simply mark arevision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. to a certain branch usingjj bookmark set branch_name -r ID. This is really useful when I decided that some of myrevisions A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. belongs to a different branch. -
Playing around with changes
There’s no need for
git commitin Jujutsu, so it lets me play around withrevisions A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. . I can move around between them, consider this scenario:- I have a
revision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. calledfeat/auth(it’s abookmark Bookmarks are Jujutsu's equivalent of Git branches. They're named pointers to revisions that move when you create new descendants. ) - I want to try implementing an OAuth flow, so I do
jj new feat/authto create a childrevision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. usingfeat/authas itsparents A parent revision is the ancestor that a revision is based on. Revisions form a tree structure where each can have one or more parents. , do some changes, let’s call thisauth-a - I then realise I can do things differently, so I just do
jj new feat/authagain and create a child, which will be the sibling ofauth-b - Now
auth-bhas a bunch of changes, let’s say they’reauth-b-1andauth-b-2 - As I’m working on
auth-b-3, I realise that if I doauth-b-2a bit different, things can be a lot simpler, so I can either dojj new auth-b-1to create a sibling toauth-b-2and continue working from there, or simply dojj edit auth-b-2to go back toauth-b-2and do things a bit different. - After I’m satisfied, I can set the
bookmark Bookmarks are Jujutsu's equivalent of Git branches. They're named pointers to revisions that move when you create new descendants. toauth-b-4, which is the final version after I play around with several solutions, and push it to remote - I then do
jj abandona few times to remove therevisions A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. that I no longer need.
You see, this is really, really flexible to experiment with. You can move wherever you want! You can’t really do this using Git unless you want to have several branches, which is less flexible in my opinion.
- I have a
-
Deferring conflicts
My mate and I like to do rapid changes a lot of the times, and sometimes we have conflicts whenever we try to sync the changes. The fact that I can leave that for later is great! I don’t want to deal with
bun.lockconflicts,README.mdconflicts, or any of those things while I’m working on the core feature. I don’t want to break my momentum. You can’t do this in Git because you have to resolve the conflicts whether you want it or not. -
Moving between branches at ease
Sometimes when I’m working on a feature, some urgent things happen that requires me to move to the other branch. Traditionally in Git, I have to either stash the
changes In Jujutsu, changes represent your uncommitted modifications. Unlike Git's staging area, all changes are automatically tracked and snapshotted. , or make a WIP commit, which could easily get messy. In Jujutsu, however, none of that is needed. I can simply move to the otherbookmark Bookmarks are Jujutsu's equivalent of Git branches. They're named pointers to revisions that move when you create new descendants. because all mychanges In Jujutsu, changes represent your uncommitted modifications. Unlike Git's staging area, all changes are automatically tracked and snapshotted. will stick to therevision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. I’m working on. I can simply do:- Move to other
bookmark Bookmarks are Jujutsu's equivalent of Git branches. They're named pointers to revisions that move when you create new descendants. that’s urgent, i.e.jj new staging - Do some fixes,
jj describe -m "fix broken stuff"and move thebookmark Bookmarks are Jujutsu's equivalent of Git branches. They're named pointers to revisions that move when you create new descendants. usingjj b set fix/broken-stuff, and then push to remote usingjj git push --bookmark feat/auth - Back to my main
revision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. by doingjj edit my-ongoing-work.
This is really simple and easy to do, it’s also fast because you worry about less things, you can just move around.
- Move to other
-
Squashing and splitting changes
My workflow is pretty messy, sometimes I don’t do things in the right order, after committing my changes it’s impossible to change using Git, but it’s pretty flexible with Jujutsu. Let’s use this post as an example :)
While I was working on this post, I realised that I can cache the PR loader that you see on the homepage of my website, so I just do that before I forgot. However, I’m still in the same
revision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. as this post and I like to have a clean history. So, I split thechanges In Jujutsu, changes represent your uncommitted modifications. Unlike Git's staging area, all changes are automatically tracked and snapshotted. into multiple commits, and all is good!Another messy things I do is when I’ve finished a feature, I do
jj new, but then in the middle of doing things, I realise that this isn’t worth a new commit/revision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. , so I just squash thisrevision A revision is Jujutsu's equivalent of a commit, but unlike Git commits, they remain mutable until pushed to a remote. with itsparent A parent revision is the ancestor that a revision is based on. Revisions form a tree structure where each can have one or more parents. , and then continue with my work. -
Undoing my screw ups
Like I said, I’m pretty messy when it comes to working on something, and I sometimes make mistakes. Incorrect amend, wrong rebase target, screwing up a rebase, accidentally removed untracked files because I didn’t check before doing
git reset --hard. I usually don’t bother with fixing things up when I was using Git because it’s so painful with the whole reflog thing. I just give up, accept that I’ve screwed up, and start over again. With Jujutsu, I actually recover from those mistakes. Any operation screw up that I did can be easily undone in a safe and incremental way. I can walk back one step at a time without having to worry about the pain of going through the reflog.
These are just some of my workflows that hopefully give you an idea of how I use Jujutsu on my day to day work. Although, I don’t do these things manually, I use jjui which is a TUI version of Jujutsu. It’s very intuitive since you see all the
Closing Thoughts
Honestly there’s still a lot of things that I haven’t explored in Jujutsu and haven’t covered in this post, this is just scratching the surface. I thought it’d be fun to write some of them so I can give answer to people if they ask me why I prefer Jujutsu over plain Git.
In general Jujutsu just feels like a better Git experience, everything makes more sense to me, a lot of commands just feel more intuitive to use and figure out.
Bear in mind, I’m not trying to sell you Jujutsu, this is purely my personal opinion of using it. If anything I feel like it’s impossible for me to convince you to use Jujutsu if you’ve been using Git for years and worry about compatibilities that ruins your workflow.
It’s one of those things that you need to try it yourself for quite some time for you to feel its benefit. I haven’t used Git for a few months now, and whenever I get back I miss Jujutsu’s working copy and
You can see all of my Jujutsu configs in my dotfiles repo.
References
There’s A LOT in Jujutsu, here are some of the resources I found useful when exploring how it works. Hope it also helps you!
- Jujutsu Documentation
- Steve’s Jujutsu Tutorial
- Towards an AI-Native Development Workflow (Using Jujutsu as the Backbone)
- Jujutsu worktrees are very convenient!
- Jujutsu Bits and Booze by Gitbutler
- DevOps Toolbox Jujutsu Overview
- Jujutsu: A Git-compatible VCS - GitMerge 2024
- Jujutsu, a Git compatible VCS - Tony Finn
If you don't see any comment section, please turn off your adblocker :)