LinuxCommandLibrary

git-range-diff

Compare commit ranges between two branches

TLDR

Diff the changes of two individual commits

$ git range-diff [commit_1]^! [commit_2]^!
copy

Diff the changes of ours and theirs from their common ancestor, e.g. after an interactive rebase
$ git range-diff [theirs]...[ours]
copy

Diff the changes of two commit ranges, e.g. to check whether conflicts have been resolved appropriately when rebasing commits from base1 to base2
$ git range-diff [base1]..[rev1] [base2]..[rev2]
copy

SYNOPSIS

git range-diff [options] <range1> <range2>

PARAMETERS

<range1>
    The first commit range to compare. This can be specified as a single commit, a branch name, or using the '..' or '...' notations (e.g., commitA..commitB).

<range2>
    The second commit range to compare. Similar to <range1>, it can be a commit, branch, or range specification.

--stat
    Show a diffstat (summary of changes) instead of the full patch for each paired diff.

-p, --patch
    Show the patch output. This is the default behavior if no other diff options are given.

--no-color
    Turn off colored output, which is on by default.

--diff-options=options
    Pass arbitrary options directly to the underlying `git diff` command used for comparing paired patches.

--no-merges
    Do not include commits that are merges in the ranges. This is useful when comparing linear histories.

--single-parent, --no-single-parent
    When walking history, act as if all commits have only one parent. Useful for comparing rebased branches without being distracted by merges. --no-single-parent is the default.

--creation-factor=factor
    Tune the heuristic for pairing up renames or copies. A value between 0 and 1, with a default of 0.6.

--range-diff-path=path
    Limit the comparison to changes affecting a specific file or directory path. This option can be repeated.

--submodule-range-diff
    When comparing commits that touch submodules, show detailed range-diff output for the submodule as well, instead of just the commit ID change.

DESCRIPTION

The `git-range-diff` command is designed to compare two arbitrary commit ranges (e.g., branches, or sets of commits) by analyzing the patches introduced within each range. Unlike `git diff` which compares two specific states of a repository, `git-range-diff` compares sequences of changes. It's highly useful for understanding the differences between two versions of a topic branch, especially after a rebase operation, or for reviewing how a series of patches evolved. It intelligently attempts to pair up corresponding commits between the two ranges, then shows the differences in the patches of those paired commits, or highlights commits that are unique to one range or the other. This provides a high-level overview of how two branches or commit series diverge or converge in terms of their applied changes.

CAVEATS

Comparing very large or highly divergent commit ranges can be computationally intensive and slow. The heuristic for pairing commits might not always find the 'intended' pairing, especially when commits have been heavily rewritten or reordered. Interpreting complex `range-diff` outputs requires familiarity with its specialized symbols and structure.

HOW IT WORKS

The command first computes a 'similarity score' between all pairs of commits in the two ranges. It then attempts to find an optimal matching of commits that maximizes these scores, using a longest common subsequence (LCS) algorithm. For paired commits, it shows the diff between their respective patches. For unpaired commits, it indicates if they are unique to one range or the other.

OUTPUT FORMAT

The output uses special prefixes to denote the relationship between commits and their patches:
=: An identical commit (same subject and patch) is found in both ranges.
<: A commit is unique to the <range1> (the first range).
>: A commit is unique to the <range2> (the second range).
:: A commit from <range1> is paired with a commit from <range2>, but their patches differ (a 'modified' patch). The subsequent lines show the diff between the two patches.

USE CASES

`git-range-diff` is invaluable for:
- Comparing a topic branch before and after a rebase operation to see how patches were modified or reordered.
- Reviewing a patch series submitted by a developer against a revised version.
- Understanding the differences between two forks of a repository that maintain similar series of changes.

HISTORY

The `git-range-diff` command was introduced in Git version 2.19 (released in August 2018). It filled a significant gap in Git's capabilities for comparing and reviewing series of changes, particularly in workflows involving frequent rebasing or patch series management.

SEE ALSO

git diff(1), git log(1), git rebase(1), git cherry-pick(1)

Copied to clipboard