Jesse Lawson


Pull requests, fetching, and merging in jj

jj-vcs

A git workflow I’m used to looks like this:

My intention is to bring my local version of main, onto which I am building my new feature, up to date with what is now considered the latest version of the codebase that lives in the remote repository at origin.

Using jj, I can achieve the same workflow with just a few different commands.

# Create the jj-equivalent of a branch

In jj, there’s no such thing as “branches” per se, but there are similar abstractions called “bookmarks”.

I’ve been working on an update to the CLI tool tasty, and just ran jj squash to bring my working copy changes into the parent commit, giving me 1) a clean working copy (e.g., no new changes to account for), and 2) a commit for a new bookmark.

Here’s the current status:

jj screenshot

And here’s a snippet of the log:

jj screenshot

I’ll create a new bookmark that will will serve as the git branch for the pull request I’ll create in GitHub:

jj bookmark create add_debug_info -r tt

Here I’m creating a new boomark named add_debug_info and attaching it to the revset starting with tt. Afterwards, I’ll get the status (jj st) so that I can see the new bookmark on the correct revset:

jj screenshot

# Push to remote

Next, I’ll push this up to origin:

jj git push --allow-new

This tells jj to push the bookmark of the current parent commit, and that you want it to create a new branch on the remote.

If you omit the --allow-new flag, jj will not push anything and instead remind you to include it.

jj screenshot

Our new branch add_debug_info has been created in the origin (GitHub), and now I can go there and create this pull request:

gh screenshot

Since it’s just me working on this right now, I’ll go ahead and merge this PR. I choose to create a merge commit because that’s how I like to do things. Now my remote trunk includes the add_debug_info branch–which is associated with my local jj bookmark add_debug_info.

jj screenshot

# Fetch and merge the remote changes

Back in my local version of the code, I’m ready to bring in the changes that have just been merged into remote.

The first thing I’ll do is fetch the changes with jj git fetch:

jj screenshot

Now I have the latest version of trunk, but it’s not integrated into my codebase just yet.

In fact, jj helps you visualize this. Run jj log right now, and you’ll see the fetched merge commit from GitHub off to the side:

jj screenshot

I don’t have anything I want to test or do before integrating these changes into my local copy, so I’m going to go ahead and bring them over with jj rebase:

jj rebase -d trunk

jj screenshot

This rebases the commit onto the default destination, which is the current parent commit:

jj screenshot

Now we have our local copy of trunk synced with the remote source-of-truth that was just updated from a pull request.