-
Notifications
You must be signed in to change notification settings - Fork 1
title: quick jujutsu subtitle: a quick guide to jj on git created: 2025-10-31 updated: 2025-11-18 author: dozens toc: true toc-title: Contents
These notes are a little bit of a mess because I made them myself, for myself. Sorry slash you're welcome!
I am jujutsu curious because it seems like it might be a more simple and ergonomic alternative to git.
Really, just look at its tagline!
A Git-compatible VCS that is both simple and powerful
I am interested in:
#. trunk-based branch-agnostic development, #. merges and rebases that always succeed, #. freedom to edit any change without having to git rebase, and #. the novelty and freedom of working without an index or staging area.
I want to evaluate jj for use at work. Because jj can use git as a backend, and can seamlessly colocate with git, it's possible to use it without disrupting collaboration, and without anybody knowing about it if you don't want them to.
But in order to evaluate it, I gotta learn how to use it a little bit first!
Here are some fundamentals / paradigms.
-
Auto committing. Every change you make is auto-committed. You don't really directly interact with commits any longer, but instead with changesets. Commits are kind of backgrounded and can change. But change ids are pretty constant.
-
No Index, No Staging. Because commits happen automatically, they are heavily de-emphasized conceptually. And so there is no index, because there is really no need for one. When everything is added to the staging area by default, the concept of a staging area kind of loses its meaning. You can still split and rebase changes as needed. You just don't have to stage anything. Because there is no stage, you don't have to worry about unstaged commits before jumping somewhere else in the tree. This is something I love. No more
git stashandgit stash pop, no more quickgc -am 'WIP'before jumping away. -
Anonymous branches: Git cares deeply about branches. The first thing you have to do when preparing to make changes is to name your branch. jj doesn't care about branches. You can just start making changes, and then describe your changes whenever you want. Jumping around between changes, and resolving conflicts, and rebasing are all so easy that there's not that much need for named branches. You can just start making changes as needed.
-
Sneaky: Because jj sits right on top of git and interops with it seamlessy, you can start using it at work if/when you find it superior to git commands and workflows, and nobody ever has to know.
Assumes MacOS.
-
Install jj:
brew install jj -
Install shell completions:
eval "$(jj util completion zsh)"Or whatever your shell is. Put it at the end of your zshrc/bashrc/whatever. -
Do the tutorial:
jj help -k tutorialIt is admittedly a little out of date. But it'll show you all the basics.
How to do a git. Or, how to use jj when your code is already in a git repo.
Parts of jj (branches and remotes, pushing and pulling) rely on git.
jj currently has no transport capabilities.
You must rely on git push and git pull to move code from one place to another.
You can either just use git commands,
or do jj git push,
jj git fetch,
jj git remote,
etc.
jj has no branches, not really. Not like git does. But can interact with git branches via bookmarks.
read jj help -k bookmarks
Clone a git repo.
e.g.: git clone https://git.tilde.town/dozens/tarot.git
Navigate to your project: cd tarot
Initialize jj to colocate with git: jj git init --colocate
(Note:
--colocate might be the default for jj git init now?)
Done importing changes from the underlying Git repo.
Setting the revset alias `trunk()` to `main@origin`
Hint: The following remote bookmarks aren't associated with the existing local bookmarks:
main@origin
Hint: Run the following command to keep local bookmarks updated on future pulls:
jj bookmark track main@origin
Initialized repo in "."
Hint: Running `git clean -xdf` will remove `.jj/`!
This creates a bookmark called main corresponding to the git branch.
In the future whenever you are ready to share your code you can give a revid a bookmark name, and then git push that to your remote.
jujutsu supports anonymous branches and trunk-based development. You don't need to create a new branch to start developing. Every change you make is committed as you make it. That's why jj has the concept of both commit ids and change ids.
Commit ids will change as you make edits to changes. Change ids will not.
::: aside
Commit ids are in hexadecimal:
0123456789abcdef
Change ids are the rest of the alphabet:
ghijklmnopqrstuvwxyz.
So you can always tell a commit from a change
by looking at its id.
:::
-
jj/jj log: show log. Note that the log doesn't show you everything by default. It shows you what is most immediately relevant. See:jj log --help -
jj st: status -
jj diff: diff between changes
So you can just start making changes to main.
-
jj new: Start a new change -
jj describe: Describe it. Now, or later.
That's really it. No git branch, git add, git commit, git merge.
The most basic workflow
-
jj new: start new changeset -
jj describe: describe the work you're about to do - Do the work
- Repeat
Squash workflow
-
jj new <changeid>(Where<changeid>is the id you want to base your change on.) This is your base change. Describe it:jj describe -m 'msg' - Make a new empty change:
jj new. Yes, that's Double New. This is kind of like a feature branch or a wip branch. - Make your changes.
-
jj squash: squash them changes. Now they're on your base changeset. (OR,jj squash -ito fire up the TUI and squash smaller Interactive changes)
Tutorials, How-Tos, and Guides
- https://github.com/jj-vcs/jj
- https://jj-vcs.github.io/jj/latest/
- https://steveklabnik.github.io/jujutsu-tutorial/introduction/introduction.html
- https://jj-for-everyone.github.io/
- https://reasonablypolymorphic.com/blog/jj-strategy/index.html
- https://v5.chriskrycho.com/essays/jj-init/
- https://www.stavros.io/posts/switch-to-jujutsu-already-a-tutorial/
- https://neugierig.org/software/blog/2025/08/jj-bookmarks.html
- https://www.rahuljuliato.com/posts/jj-cheat-sheet
Tooling
- https://github.com/idursun/jjui TUI for jj
- https://github.com/julienvincent/hunk.nvim A tool for splitting diffs in Neovim
- https://github.com/rafikdraoui/jj-diffconflicts A conflict resolution merge tool for Jujutsu VCS that runs in Neovim
- https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/jj Plugin for oh-my-zsh
- https://github-wiki-see.page/m/jj-vcs/jj/wiki/Starship Configuring Starship prompt for jj