While working on a repo that has a lot of divergent then merged branches, I was reviewing a merge request on Github. I wanted to take a look at the changes in more detail from the terminal, but found that I couldn’t quite get the same diff.

Github’s diff view is based on main...feature, where we are merging feature into main. What this actually means is that we take a diff from the latest common commit between the two branches and the feature branches. I typically do such diffs using the equivalent of main..feature, but if main has been merged in part way through the feature, this is not quite right.

Getting the equivalent base commit to ... in jj’s revset syntax is pretty simple: heads(::main & ::feature).

Breaking that down

::main & ::feature <= intersection of all commits on main and feature

heads() <= Filter to only commits without descendants (leaves)

heads(::main & ::feature) <= Last shared commit(s)

Most of the time, you will only have one commit from this and can use it as a base for the diff:

jj diff --from 'heads(::main & ::feature)' --to feature

The exception is when we have “branched” using a “merge” (the first commit that deviated from your trunk branch has two parents, both of which are on the trunk branch). That is kind of odd and I have not encountered that in practice yet (though I’m sure there will be genuine examples out there!).