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.

Mega-Merge Workflow Mega-Merge: Asciicast MP4

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!

Post comment via email