jr (Jujutsu Review) is a Rust-based CLI tool for translating Jujutsu commits
into stacked GitHub PRs.
NOTE: This is alpha quality software. Although I'm using it myself, it hasn't seen extensive use in the wild. There will be bugs.
jr operates by associating each Jujtsu change with a remote "PR branch". As
the change evolves, jr will (i) add new commits to the PR branch in order to
keep its contents synchronized, and (ii) use the GitHub API to update the
corresponding PR.
This tool is inspired by:
- Phabraciator Arcanist (
arc) CLI tool - Super Pull Requests; we use a similar
initflow.
Clone this repo and run:
cargo install --path .By default, cargo install places binaries in ~/.cargo/bin/. Make sure this
directory is in your PATH:
export PATH="$HOME/.cargo/bin:$PATH"Run jr init in the root of a git-backed Jujutsu repository to setup
configuration.
To see the status of all pull requests in your stack:
jr statusTo create a new PR from the current commit:
jr createTo update a PR with your changes to the current commit:
jr update -m "My commit message"To merge in changes from an updated base branch:
jr restackPreserving history is the raison d'être for this tool. If we instead force-push
our changes, using e.g. jj git push, then the GitHub review experience really
degrades:
- There's no way for reviewers to only see changes since their last review.
- Review comments are dropped / duplicated / moved; Github has to use heuristics to map old review comments onto the new branch. These heuristics don't always work.
To avoid confusing reviewers, they shouldn't be aware that we're using Jujutsu. Instead, they should think "Yes, I can see how to do all of this using standard Git practices. But boy oh boy, it looks like it's a lot of work keeping all of these branches synchronized. I'll stick to using uber branches."
In more detail:
- Each Jujutsu commit is mapped onto a single remote Git branch, using the remote branch of the previous Jujutsu's commit as its base. (This is in contrast to Super Pull Requests, where each PR has its own corresponding base branch.)
- Changes to an existing Jujutsu commit should appear as a new commit on the remote Git branch, with a suitable comment.
- Changes to base branches should be incorporated into the current branch using a merge commit.
This keeps things simple, and is what I use.
jr is just some coordination glue; it uses jj, git and curl to perform
the actual work. (It could have been implemented as a shell script, although
the results wouldn't have been pretty.) I chose this approach in order to
minimize the number of Rust dependencies. And, I could probably still remove a
few more dependencies.
Note that we're using curl instead of the gh GitHub CLI because you might
not have gh installed (and it's not that hard to make a few curl requests to
the GitHub API).
The PR branch name is computed by appending the first eight digits of the Jujutsu change ID to the configured branch prefix. There is currently no way to override this, although I can imagine extending the current configuration system to accomodate this.
The synchronization is strictly one-way; there is no way to update (or recreate) a set of Jujutsu changes from a set of stacked GitHub PRs.