This content originally appeared on DEV Community and was authored by Cristian Sifuentes
TL;DR — Use
A...Bfor “what actually differs since the common ancestor”,A..Bfor “what’s in B that isn’t in A”. Start with ahead/behind counts and a stat diff, then drill into commit graphs, rename‑aware diffs, and range‑diff for rebases.
Table of Contents
- Quick Answers (copy/paste)
- Double vs Triple Dots (mental model)
- File & Content Diffs That Read Well
- Commit‑Level Analysis (surgical view)
- What Will Actually Merge? (merge‑base)
- Triage & Impact (where the churn lives)
- Review‑Ready Workflows (pre‑PR / dry‑run)
- Windows / PowerShell Equivalents
- Pro Aliases (drop‑in)
- Decision Cheatsheet
Quick Answers (copy/paste)
Replace
A/Bwith your branches (e.g.,origin/mainandfeature/payments).
# How far apart are they?
git rev-list --left-right --count A...B # → <A-only> <B-only>
# High-level file summary
git diff --stat A...B
# Full content diff (triple dot: versus merge-base)
git diff A...B
Graph + commits per side:
git log --oneline --left-right --cherry-pick --graph A...B
Names only / status:
git diff --name-only A...B
git diff --name-status A...B # A/M/D/R status
Detect renames/moves better:
git diff -M -C A...B
Double vs Triple Dots (mental model)
| Pattern | Interprets As | Use For |
|---|---|---|
A..B |
commits in B not in A | “What would I pull from B into A?” |
A...B |
compare each side vs merge‑base(A,B) | “What actually differs since we diverged?” (PR view) |
Find the merge base explicitly:
git merge-base A B
File & Content Diffs That Read Well
# Files changed (names only / with status)
git diff --name-only A...B
git diff --name-status A...B
# Ignore whitespace noise
git diff -w A...B
# Word-level (docs/markdown)
git diff --word-diff A...B
# Function/context aware (C/C++/Java/C#)
git diff -W A...B
# Focus a path/glob
git diff A...B -- src/api/**.cs
Rename/move detection boosters:
git diff -M -C --stat A...B
Commit‑Level Analysis (surgical view)
Linearized graph with sides marked:
git log --oneline --graph --decorate --left-right --cherry-pick A...B
Which commits from B are not in A (cherry candidates):
git cherry -v A B
Compare two series of commits (e.g., before/after rebase):
git range-diff oldA..oldB newA..newB
# common real-world: compare 'topic' before/after rebase onto 'main'
git range-diff origin/main..feature v2/main..feature
What Will Actually Merge? (merge‑base)
Preview conflicts safely:
git switch A
git merge --no-commit --no-ff B # dry run
git merge --abort # back out
Show deltas vs merge‑base:
mb=$(git merge-base A B)
git diff --stat $mb A
git diff --stat $mb B
Triage & Impact (where the churn lives)
Top churn files in this comparison:
git diff --numstat A...B | sort -k1,1nr | head
# columns: added removed path
Authorship focus for a hot file:
git blame B -- path/to/file | cut -d'(' -f2 | cut -d' ' -f1 | sort | uniq -c | sort -nr
Extension distribution (what kind of work changed):
git diff --name-only A...B | awk -F. '{print $NF}' | sort | uniq -c | sort -nr
Review‑Ready Workflows (pre‑PR / dry‑run)
A) What your PR actually changes
git fetch origin
git diff --stat origin/main...HEAD
git log --oneline --left-right --cherry-pick origin/main...HEAD
B) Safety check before merging B into A
git switch A
git merge --no-commit --no-ff B
git merge --abort
C) Cherry-pick only the good stuff
git cherry -v A B | grep '^+' | awk '{print $2}' | xargs -I{} git cherry-pick {}
Tip: On protected branches (Azure DevOps/GitHub), prefer PRs over history edits. Use
range-diffto prove your rebase didn’t change semantics.
Windows / PowerShell Equivalents
PowerShell doesn’t have xargs by default; use loops.
# Ahead/behind
git rev-list --left-right --count A...B
# Commit graph (works the same)
git log --oneline --left-right --cherry-pick --graph A...B
# Cherry-pick (+ commits from B)
$commits = git cherry -v A B | Select-String '^\+' | ForEach-Object { ($_ -split ' ')[1] }
foreach ($c in $commits) { git cherry-pick $c }
Prefer Git Bash or WSL for the awk|xargs one‑liners:
git diff --name-only A...B | awk -F. '{print $NF}' | sort | uniq -c | sort -nr
Pro Aliases (drop‑in)
Put these in ~/.gitconfig:
[alias]
aheadbehind = rev-list --left-right --count
lg = log --oneline --graph --decorate
lga = log --oneline --graph --decorate --all
cmp = !sh -c 'git lg --left-right --cherry-pick "$1...$2"' -
whatmerges = !sh -c 'mb=$(git merge-base "$1" "$2"); echo MERGE-BASE:$mb; git diff --stat $mb "$1"; echo ----; git diff --stat $mb "$2"' -
rdiff = range-diff
Usage:
git aheadbehind A...B
git cmp A B
git whatmerges A B
Decision Cheatsheet
-
High‑level difference fast →
git diff --stat A...B+git aheadbehind A...B -
Exact commits differing →
git log --left-right --cherry-pick A...B -
Preview merge conflicts →
git merge --no-commit --no-ff Bon branch A, then--abort -
Compare two rebases/series →
git range-diff old..new base..topic -
Renames/moves matter → add
-M -Ctogit diff -
Windows shell → prefer Git Bash/WSL for
awk|xargs, or PowerShell loops
✍️ Written by: Cristian Sifuentes — Full-stack developer & AI/JS enthusiast, passionate about React, TypeScript, and scalable architectures.
This content originally appeared on DEV Community and was authored by Cristian Sifuentes
Cristian Sifuentes | Sciencx (2025-10-23T20:45:13+00:00) Git Branch Comparison — A Senior Dev’s Playbook (Concise Expert). Retrieved from https://www.scien.cx/2025/10/23/git-branch-comparison-a-senior-devs-playbook-concise-expert/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.
