Can somebody explain the usage of git range-diff?

A "range" in Git parlance is a pair of revision identifiers (start and end).

The first form of usage for git range-diff is <range1> <range2>. Since we know a range is a pair of revision identifiers, some possible examples are:

abc1234..def5678 9876foo..5432bar
HEAD..def5678 my_release_1_1..my_release_1_2

The other two forms of usage are for convenience when some of the four revision identifiers are the same as each other. Namely:

  1. For a case like abc..def def..abc, you can simply specify def...abc.
  2. For a case like abc..def abc..xyz, you can specify abc def xyz. This seems like a common case to me: you want to compare two ranges which start at the same point.

Range diff is very useful right after resolving merge conflicts (after rebase, cherry-pick, etc.), especially when you had multiple conflicting commits, and you want to make sure that you haven't accidentally broken something during the process.

Here is a scenario that usually happens in case you are doing multiple commits in a branch.
Let's say we have a branch called "our", and our branch is behind the master branch:

m1-m2-m3-m4  <- "master" branch
  \
   o1-o2-o3  <- "our" current branch

Before rebasing, we do a backup of our branch (just make a copy branch with the name "our_bkp")

git branch our_bkp

Then we initiate rebasing with the master

git rebase master

And solve some of the merge conflicts on the commit "o1"...
Note: If the conflicting files on the "o1" were also used/changed in "o2" or "o3",
then we'll have to re-resolve the same merge conflicts on them as well.

Now, let's say after an exhausting rebase process we have something like this:

             _<- branch "master"
            /
 m1-m2-m3-m4-o1'-o2'-o3'  <- branch "our" (after rebase)
  \
   o1-o2-o3   <- branch "our_bkp"
   

Since there were many merge conflicts, it's not clearly visible whether we've missed something or not.

And this is where the range-diff shines.

To make sure that we haven't missed any change or accidentally damaged anything, we can simply compare our commits from the old version of the branch with the newer version:

git range-diff our_bkp~3..our_bkp our~3..our

or

git range-diff o1..o3 o1'..o3'

If the diffs are only related to the conflicting parts, then we are good, and haven't changed anything other than them.
But if we see some other unexpected diffs, then we or git did something wrong, and we'll need to fix them.

Notes

  • Both of the range-diff commands above are doing exactly the same thing.
  • By saying o1..o3 I mean the numbers of those commits, e.g.: 0277a5883d132bebdb34e35ee228f4382dd2bb7..e415aee3fa53a213dc53ca6a7944301066b72f24
  • The ~3 in our_bkp~3 says git to take the commit that was 3 commits before the last one on our_bkp branch. Replace the number with the amount of the commits you had on your branch and of course don't forget to replace the branch name our_bkp with your backup branch's name.
  • You can consider the range-diff as doing a diff of two diff-s. This way it'll be easier to remember and understand what it's doing.

I have not actually used them yet, but they are meant as an improvement over the old git cherry* flow for analysing / comparing some upstream or downstream change-set vs what you have now. To make the range-sets useful we want some set of "here are my commits" and "here are theirs", expressed as simply as possible.

A range1 range2 set would be written as, e.g.:

git range-diff theirs~5..theirs ours~4..ours

if you had, e.g.:

          T1--T2--T3--T4--T5   <-- theirs
         /
...--o--*   <-- base
         \
          O1--O2--O3--O4   <-- ours

where the O commits are "ours" and the T commits are "theirs".

Given this exact same configuration, however, we could also write:

git range-diff theirs...ours    # or ours...theirs

(note the three dots). (This is the syntax used with git rev-list --cherry-mark --left-right, for instance.)

Or, again given this same situation, we could write:

git range-diff base theirs ours   # or base ours theirs

Here base is the stop point for both theirs and ours, and avoids having to count back 5.

If the situation is more complicated—as in the graph:

          X1--T1--T2--T3   <-- theirs
         /
...--o--*   <-- base
         \
          Y1--Y2--O1--O2--O3--O4   <-- ours

neither the three-dot nor the base ours theirs kind of syntax quite works, so the two sets of ranges (theirs~3..theirs ours~4..ours) would be best.

Tags:

Git