git range-diff: Quick Reference¶
Compare two commit ranges after a rebase, subtree pull, cherry-pick batch, or force-push. Pair commits on the old side with commits on the new side and show the patch delta between matched pairs.
Syntax¶
git range-diff <old-base>..<old-tip> <new-base>..<new-tip>
git range-diff <old-range> <new-range> # implicit HEAD on new side
git range-diff A B # HEAD vs B
Reading the output¶
| Symbol | Meaning |
|---|---|
1: abc123 = 2: def456 |
Commit is byte-identical on both sides |
1: abc123 ! 2: def456 |
Commit exists on both sides but the patch changed |
1: abc123 < -: ------ |
Commit removed on the new side |
-: ------ > 2: def456 |
Commit added on the new side |
A clean rebase is a wall of = lines. Anything else needs review.
Common DevOps patterns¶
# 1. Validate a feature-branch rebase before review
git range-diff origin/main@{pre-rebase-sha} origin/main..feature/payments
# 2. Audit a vendor subtree pull
git rev-parse HEAD > /tmp/vendor-pre.txt
git subtree pull --prefix=lib/vendor library-repo main --squash
git range-diff $(cat /tmp/vendor-pre.txt)..HEAD^2 HEAD^2..HEAD
# 3. Audit a cherry-pick batch onto release branch
git range-diff main..@{yesterday} release/2.x..release/2.x@{0}
# 4. Validate a force-pushed stacked branch
git range-diff origin/pr/42@{1} origin/pr/42
Useful flags¶
git range-diff --no-patch A B # only summary lines, no patch diffs
git range-diff --creation-factor=80 A B # stricter pairing (more new commits as adds)
git range-diff --creation-factor=30 A B # looser pairing (more forced matches)
git range-diff --diff-merges=first-parent A B # for merge-heavy ranges
Pre-merge CI gate (Forgejo Actions)¶
- uses: https://code.forgejo.org/actions/checkout@v4
with:
fetch-depth: 0
- name: range-diff gate
run: |
git fetch origin "${{ github.base_ref }}"
changes=$(git range-diff --no-patch \
origin/"${{ github.base_ref }}"..HEAD \
origin/"${{ github.base_ref }}"..HEAD | \
grep -E '^[<>!]' || true)
if [[ -n "$changes" ]]; then
echo "Range diff detected substantive changes; manual review required:"
echo "$changes"
exit 1
fi
Pairing with safe force-push¶
# Contributor pushes with --force-with-lease so reviewers can diff against the prior SHA
git push --force-with-lease=refs/heads/pr/42:abc1234 origin pr/42
# Reviewer side: range-diff the pre-push and post-push tips
git fetch origin pr/42
git range-diff origin/pr/42@{1} origin/pr/42
Gotchas¶
- Pairing uses commit message, then author time, then patch similarity. Rename a message mid-rebase and pairing breaks.
- A split-or-merged commit shows as both a removal and an addition.
- Range-diff compares patches, not behaviour. A patch change that's actually
identical (e.g., optimiser-equal reordering) still shows
!. Run tests. - Output can be long. Use
--no-patchfor the summary,| lessfor paging. range-diffneeds both sides locally. Shallow clones:git fetch --unshallowfirst or fetch the base branch explicitly.