zsh-git-to-jj
January 1, 2026 · View on GitHub
🗣️ this is a useful plugin to help you memorize + better understand how Jujutsu works, but it's not a replacement for learning the mental model or deeper strategies.
A zsh plugin for progressively learning Jujutsu (aka jj) porcelain as you use git commands.
The plugin has two modes:
fyimode (default): shows you thejjequivalent, but still runs thegitcommand as-is.rewritemode: rewrites your git command to thejjequivalent, so that you're interacting withjjdirectly + your shell history is jj.
# fyi mode
$ git commit -m "add feature"
jj equivalent: jj commit -m "add feature"
[main abc1234] add feature
1 file changed, 10 insertions(+)
# rewrite mode (after pressing enter, command is rewritten)
$ git commit -m "add feature"
$ jj commit -m "add feature" # <- press enter again to execute
The plugin uses ZLE (Zsh Line Editor) to intercept commands on-the-fly, and is thus zsh-only.
Install
oh-my-zsh
Clone into the custom plugins directory:
git clone https://github.com/elithrar/zsh-git-to-jj.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/git-to-jj
Then add git-to-jj to your plugins array in .zshrc:
plugins=(... git-to-jj)
vanilla zsh
Clone the repository and source the plugin in your .zshrc:
git clone https://github.com/elithrar/zsh-git-to-jj.git ~/.zsh/zsh-git-to-jj
echo 'source ~/.zsh/zsh-git-to-jj/git-to-jj.plugin.zsh' >> ~/.zshrc
Antigen
antigen bundle elithrar/zsh-git-to-jj
zplug
zplug "elithrar/zsh-git-to-jj"
zinit
zinit light elithrar/zsh-git-to-jj
Configuration
Mode
Set your preferred mode by adding to your .zshrc (before sourcing the plugin):
# Options: fyi (default), rewrite
export GIT_TO_JJ_MODE=fyi
You can also switch modes at runtime:
$ git-to-jj-mode rewrite
git-to-jj mode set to: rewrite
$ git-to-jj-mode
Current mode: rewrite
Available modes: fyi, rewrite
Supported Commands
The plugin covers the most common git workflows. Here's a summary of the mappings:
| Git Command | JJ Equivalent |
|---|---|
git init | jj git init |
git clone <url> | jj git clone <url> |
git status | jj st |
git diff | jj diff |
git log | jj log |
git show | jj show |
git add <files> | (automatic in jj - no staging area) |
git commit -m "msg" | jj commit -m "msg" |
git commit --amend | jj squash or jj describe |
git push | jj git push |
git pull | jj git fetch (+ jj rebase -d main@origin) |
git fetch | jj git fetch |
git branch | jj bookmark list |
git branch <name> | jj bookmark create <name> |
git branch -d <name> | jj bookmark delete <name> |
git checkout -b <name> | jj new -B <name> |
git checkout <ref> | jj new <ref> |
git switch -c <name> | jj new -B <name> |
git merge <branch> | jj new @ <branch> |
git rebase <upstream> | jj rebase -d <upstream> |
git cherry-pick <commit> | jj duplicate <commit> |
git revert <commit> | jj backout -r <commit> |
git stash | jj new @- |
git reset --hard | jj restore or jj abandon |
git reset --soft HEAD~ | jj squash --from @- |
git restore <paths> | jj restore <paths> |
git blame <file> | jj file annotate <file> |
git ls-files | jj file list |
git rm --cached <file> | jj file untrack <file> |
git remote add <n> <url> | jj git remote add <n> <url> |
For commands without a direct mapping, the plugin will display:
git-to-jj doesn't know this one!
License
Apache-2.0 licensed. See the LICENSE file for details.