Trying Jujutsu (jj) for a Week
4 min readI've been using jujutsu at work for a week now, it's been a good experience so far. I wanted to try it basically because:
- I wanted to force myself to have a clean state in my repos, I usually left many files that won't be committed
- I don't want to name branches for PRs anymore, when making small changes, fixes, etc most of the time nobody sees the branch name in the PR so why bother to give it a proper name
- I want to switch between changes in an easy way, I was using
git stash+ switching branches for this
A few concepts to keep in mind
jjdoesn't have astagearea, everychangeis itself already acommit@references current change, and@-references current change's parentjj undowill undo any action made byjj, it's really helpful- we don't have branches in
jj, we usebookmarks - we can use
jjwith anygitproject and this won't change how other work with the repository, we just runjj git init --colocateand that is just a local change
Workflows
So let's define some common workflows I needed to fulfill with jj
I don't use
gitfrom the terminal in my regular workflow, I use magit (so much faster) from Emacs so I don't type all of the belowgitcommands but I describe the process to clarify the idea
Make a quick fix
I'm working on some feature and then someone asks me to make a change in the same repo I'm working on, what I was doing before:
git stash
git fetch origin
git checkout main
git merge origin main # to start from a fresh main branch
# do the changes
git checkout -b a-branch-name-no-one-will-read
git commit -m "some message"
git push
# go back to work, go to previous branch
git checkout original-branch
git stash popNow with jj
jj git fetch
jj new main@origin
# do changes
jj describe -m "some message"
jj git push -c @
# go back to work, run jj log and search for the change-id you were at
jj edit {change-id}
jjby default will create a branch with a namepush-{change-id}, for examplepush-zxoytvwpvmxp, we can change it by creating manually abookmark(equivalent to agitbranch) but it's not necessary
Show you current changes
This will see all the current changes using regular diff format
jj show --gitReview a Pull Request
When I need to review a PR I need to test it locally
Before
git stash
git fetch origin
git checkout -b pr_branch_name origin/pr_branch_name
# review it
git checkout -
git stash popNow with jj:
jj git fetch
jj new pr_branch_name@origin
# review it
jj undo
# now I'm where I was beforeBuilding a feature
There isn't much change here, in the git side:
git fetch origin
git merge origin main
git checkout -b a-branch-name
git add -p # because we review what we're staging, we are not savages
git commit -m "this is a feature"
git pushand with jj:
jj git fetch
jj new main@origin
# do your changes
jj describe -m "this is a feature"
jj git push -c @One difference here is that in
jjwe are "forced" to commit all of the work we've done at once, we usejj commit --interactiveorjj splitto have something likegit add -pbut I'm not used to that yet
Rebasing an existing pull request
Considering we are at that PR branch already and we need to update it with latest changes from
main branch and push it updated
git fetch origin
git rebase origin/main
# we changed history so we need to push force
git push -f origin your-branchIn the case of jj we need to make one step extra because jj bookmarks doesn't follow changes by
default, once we made the rebase we need to tell jj to move bookmark to updated change.
jj git fetch
jj rebase -d main@origin
jj bookmark set your-branch -r @
# by default jj will make a push force
jj git pushRequired stuff for work
In ~/.config/jj/config.toml:
Using company email address when committing
[[--scope]]
--when.repositories = ["~/src/my-company/"]
[--scope.user]
email = "erick.navarro@mycompany.com"Signing commits
[signing]
behavior = "own"
backend = "ssh"
key = "~/.ssh/id_ed25519.pub"What about Emacs, are we going back to the terminal for version control?
Yes and no, first I need to get used to how jj works and doing it in the terminal is the best
option, by now I'm using jj-mode.el but just to switch between changes and edit description, all
of the rest commands are done in the terminal(inside Emacs obviously 😎)
Conclusion
Will I change to jj and don't use git anymore?
Nope, jj gives me more flexibility in projects where I need to make changes quickly and where I
collaborate with others, for personal projects where I'm mostly the only contributor and there is no
rush in making changes I'll stick to git (for now? 🤔)