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:

  1. fyi mode (default): shows you the jj equivalent, but still runs the git command as-is.
  2. rewrite mode: rewrites your git command to the jj equivalent, so that you're interacting with jj directly + 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 CommandJJ Equivalent
git initjj git init
git clone <url>jj git clone <url>
git statusjj st
git diffjj diff
git logjj log
git showjj show
git add <files>(automatic in jj - no staging area)
git commit -m "msg"jj commit -m "msg"
git commit --amendjj squash or jj describe
git pushjj git push
git pulljj git fetch (+ jj rebase -d main@origin)
git fetchjj git fetch
git branchjj 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 stashjj new @-
git reset --hardjj 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-filesjj 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.