tim-janik/jj-fzf
{ "createdAt": "2024-11-02T22:28:17Z", "defaultBranch": "trunk", "description": "Text UI for Jujutsu based on fzf, centering around the jj log with key bindings for common operations", "fullName": "tim-janik/jj-fzf", "homepage": "", "language": "Shell", "name": "jj-fzf", "pushedAt": "2025-11-09T19:17:45Z", "stargazersCount": 206, "topics": [ "bash-script", "cli", "command-line-tool", "fzf", "git", "jj", "jujutsu", "merge", "rebase", "squash", "terminal", "tui" ], "updatedAt": "2025-11-14T22:30:46Z", "url": "https://github.com/tim-janik/jj-fzf"}[![License][mpl2-badge]][mpl2-url] [![Issues][issues-badge]][issues-url] [![Irc][irc-badge]][irc-url]
JJ-FZF
Section titled “JJ-FZF”About jj-fzf
Section titled “About jj-fzf”JJ-FZF is a text UI for the Jujutsu VCS jj based on fzf.
All modification commands are printed on stderr to help users in learning the jj CLI.
Feature Set
Section titled “Feature Set”- Edit the current revset (list of commits) in the fzf input field with live reload of the
jj log. - Complex rebase commands just need
Alt-Rand cursor keys. - Use
Alt-Pfor a dialog to edit or simplify the parents in a merge commit. - Splitting commits needs a single key press.
Alt-Fsplits commits by file,Alt-Iuses thejj splitcommand in interactive mode. - First class Mega-Merge support:
Ctrl-Nstarts a new branch,Alt-Ninserts a new empty commit,Alt-Pedits merged branches,Alt-Oabsorbs fixes into related commits of merged branches. - Commits can be squashed (combined into a single commit) from arbitrary points in the ancestry with
Alt-Q. - A dedicated browser (
Ctrl-T) shows the evolution of each revision (change_id) and allows to inject (Alt-J) historic versions of a revision as a new commit without affecting the working copy. - Key bindings are easily discoverable in an onscreen area and via
Ctrl-Hor thejj-fzf.1manual page. - At any point the oplog can be opened with
Ctrl-Oto understand recent modifications, browse the working copy of a previous operation and restore the repository to an arbitrary earlier snapshot. - Use
Alt-Jin the oplog to “inject” past snapshots of a repository as newly created historic commits after the fact without affecting the working copy. - Snapshots are usually created with commands like
jj status, Watchman or uponSavein Emacs by using the contrib/jj-undirty.el script. - The shortcuts for repository wide undo/redo are
Alt-ZandAlt-Y. The operation log view (Ctrl-O) reflects the current state of the undo stack by marking past undo operations with⋯.
The main view centers around jj log and allows editing of the revset that is currently being displayed.
Next to it is a preview window that shows details, message and diff for the current revision.
Cursor keys change the current revision and (Shift-)Tab selects commits.
Enter can be used to browse the commit history, or to confirm if jj-fzf was started as a selector.
Various Ctrl and Alt key bindings are provided to quickly perform actions such as abandon, squash, merge, rebase, split, branch, undo or redo of a commit and more.
The commands and key bindings can also be displayed with jj-fzf --help and are documented in the wiki: jj-fzf-help
Installation
Section titled “Installation”There are several ways to install and use jj-fzf:
- Download the latest release tarball.
Extract, then run
make allandmake install PREFIX=~/.localunder a suitable prefix to runjj-fzffrom$PATHand havejj-fzf.1in$MANPATH. - Download jj-fzf.sfx, rename to
jj-fzfand mark it executable to run it directly. - Download jj-fzf.1.gz, install it under e.g.
~/.local/share/man/man1/jj-fzf.1.gz.
Internally, jj-fzf uses tools like python3, awk, sed and grep with GNU tool semantics.
Start jj-fzf in any jj repository and study the keybindings.
Various jj commands are accessible through Alt and Ctrl key bindings.
The query prompt can be used to type a new revset to be displayed by jj log.
The preview window shows commit details and diff information.
When a key binding is pressed to modify the history, the actual jj command is displayed on stderr with its arguments.
Quit jj-fzf with Escape or suspend it with Ctrl-Z to look at the execution trail.
Demo Screencasts
Section titled “Demo Screencasts”UI Introduction
Section titled “UI Introduction”The intro screen cast shows the jj log view, the commit diff preview window and a brief glimpse of the oplog (Ctrl-O).
JJ-FZF Introduction: Asciicast MP4
Splitting Commits
Section titled “Splitting Commits”This screencast demonstrates how to handle large changes in the working copy using jj-fzf.
It begins by splitting individual files into separate commits (Alt-F), then interactively splits (Alt-I) a longer diff into smaller commits.
Diffs can also be edited using the diffedit command (Alt-E) to select specific hunks.
Throughout, commit messages are updated with the describe command (Ctrl-D),
and all changes can be undone step by step using Alt-Z.
Splitting Commits: Asciicast MP4
Merging Commits
Section titled “Merging Commits”This screencast demonstrates how to merge commits using the jj-fzf command-line tool.
It begins by selecting a revision to base the merge commit on, then starts the merge dialog with Alt-M.
For merging exactly 2 commits, jj-fzf suggests a merge commit message and opens the text editor before creating the commit.
More commits can also be merged, and in such cases, Ctrl-D can be used to describe the merge commit afterward.
Rebasing Commits
Section titled “Rebasing Commits”This screencast demonstrates varies ways of rebasing commits (Alt-R) with jj-fzf.
It begins by rebasing a single revision (Alt-R) before (Ctrl-B) and then after (Ctrl-A) another commit.
After that, it moves on to rebasing an entire branch (Alt-B), including its descendants and ancestry up to the merge base, using jj rebase --branch <b> --destination <c>.
Finally, it demonstrates rebasing a subtree (Alt-S), which rebases a commit and all its descendants onto a new commit.
Rebasing Commits: Asciicast MP4
”Mega-Merge” Workflow
Section titled “”Mega-Merge” Workflow”This screencast demonstrates the Mega-Merge workflow, which 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.
Contrib Directory
Section titled “Contrib Directory”The contrib/ directory contains additional tools or scripts that complement the main jj-fzf functionality.
These scripts are aimed at developers and provide useful utilities for working with jj.
-
jj-am.sh: A very simple script that allows to apply patches to a jj repository.
Usage: ~/jj-fzf/contrib/jj-am.sh [format-patch-file...] -
jj-undirty.el: A simple Emacs lisp script that automatically runs
jj statusevery time a buffer is saved to snapshot file modifications.Usage: (load (expand-file-name "~/jj-fzf/contrib/jj-undirty.el"))This will install an after-save-hook that callsjj-undirtyto snapshot the changes in a saved buffer in a jj repository. -
suspend-with-shell.el: A simple Emacs lisp script that allows to suspend Emacs with a custom command.
Usage:;; Suspend emacs with a custom command, without using `ioctl(TIOCSTI)`(load (expand-file-name "~/jj-fzf/contrib/suspend-with-shell.el"));; Suspend emacs and start jj-fzf on Ctrl-T(global-set-key (kbd "C-t") (lambda () (interactive) (suspend-with-shell "jj-fzf")))
License
Section titled “License”This application is licensed under MPL-2.0.
Star History
Section titled “Star History”[irc-badge] !: https://img.shields.io/badge/Live%20Chat-Libera%20IRC-blueviolet?style=for-the-badge [irc-url] !: https://web.libera.chat/#Anklang [issues-badge] !: https://img.shields.io/github/issues-raw/tim-janik/jj-fzf.svg?style=for-the-badge [issues-url] !: https://github.com/tim-janik/jj-fzf/issues [mpl2-badge] !: https://img.shields.io/static/v1?label=License&message=MPL-2&color=9c0&style=for-the-badge [mpl2-url] !: https://github.com/tim-janik/jj-fzf/blob/master/LICENSE