JJ-FZF is a TUI
(Terminal-based User Interface) for Jujutsu, built on top
of fzf. It centers around
the jj log
view, providing key bindings for common
operations on JJ/Git repositories.
About six months ago, I revisited JJ, drawn in by its promise of Automatic
rebase and conflict resolution
. I have since found it very
useful and started to integrate it into my daily work. Previously, I
have been relying on shell wrappers and aliases (yyhelp)
for most of my Git interactions. To better understand JJ’s operations, I
decided to wrap the command details inside shell functions and bind them
to keys in jj log | fzf
. The result is
jj-fzf
.
Since I tend to maintain a clean, linear history in my repositories,
I found myself switching between gitk
and
git rebase -i
way too much. With having
jj squash
available at a single key press and
jj rebase
where you can specify the source as
--branch, --source, --revisions
and the target as
--destination, --insert-after, --insert-before
, this has
become a thing of the past. But, since jj
introduces
completely new ways to modify the history, having the constant feedback
that jj-fzf
provides allowed me to grow the needed
understanding of how the history evolves after certain jj
command variants. All repository modifications carried out by
jj-fzf
are printed to stderr
, which helps a
lot in debugging and serves as a good learning aid.
A major game-changer for me was the Mega-Merge Workflow as
described by Benjamin Tan. With jj
’s conflict handling,
this workflow enables to combine selected feature branches into a single
Mega-Merge
commit that the working copy is based on. This means I
can activate
or ignore feature branches as needed in my working
directory. I was pleasantly surprised by how few conflicts I encountered
with this workflow. At this point, when I do run into conflicts, I
almost never resolve them by editing the source code. Instead, conflicts
can usually be resolved with a few key presses in jj-fzf
,
such as swapping commits (Alt+X
), rebasing only a single
commit (Alt+R Alt+R
), or splitting a commit interactively
before rebasing (Alt+I
). Being able to jj undo
(Alt+Z
) a rebase attempt or other jj
operations is a tremendous help.
jj-fzf 0.22.0:
So far jj-fzf
has been residing in my
tools/
repository, but due to external demands it is now
migrated into its own repository and will get regular releases. I just
tagged the jj-fzf
0.22.0 release (which depends on jj-0.22.0
).
Mega-Merge
Workflow:
I really recommend checking out this screencast demonstrating the Mega-Merge workflow.
It allows to combine selected feature branches into a single
Mega-Merge
commit that the working copy is based on. It begins by
creating a new commit (Ctrl+N
) based on a feature branch
and then adds other feature branches as parents to the commit with the
parent editor (Alt+P
). As part of the workflow, new commits
can be squashed (Alt+W
) or rebased (Alt+R
)
into the existing feature branches. To end up with a linear history, the
demo then shows how to merge a single branch into master
and rebases everything else to complete a work phase.
If you find jj-fzf
to be interesting, leave a star in
the Github repository or hit me up with any questions you might have.
I’d love to hear about other experiences with jj
,
jj-fzf
and with the Mega-Merge
workflow!