The Hook (The "Byte-Sized" Intro)
Two dots or three? A..B and A...B look similar but mean completely different things — and they behave differently in git log vs git diff. Getting this wrong gives you the wrong answer: you'll think 5 commits changed when 50 actually did. Two minutes learning the difference saves hours of confusion.
📖 What is Comparing Commit Ranges?
Git uses .. and ... operators to define ranges of commits for comparison. Their meaning differs between git log and git diff.
Conceptual Clarity
In git log:
| Syntax | Meaning |
|---|---|
A..B | Commits in B but NOT in A |
A...B | Commits in A or B but NOT both (symmetric difference) |
In git diff:
| Syntax | Meaning |
|---|---|
A..B | Diff between A and B (same as git diff A B) |
A...B | Diff between the common ancestor of A and B, and B |
Visual example:
main: A ─ B ─ C ─ D
\
feature: E ─ F
git log main..feature → E, F (only on feature)
git log feature..main → D (only on main since fork)
git log main...feature → D, E, F (on either, not both)
git diff main..feature → diff D vs F
git diff main...feature → diff C vs F (from fork point)
Real-Life Analogy
A..B= "What did you do that I didn't?" (one-sided comparison)A...B= "What did either of us do since we split up?" (symmetric)
Visual Architecture
Why It Matters
- PR reviews:
main..featureshows exactly what a PR adds. - Release notes:
v1.0..v2.0shows all new commits. - Code review:
main...featureshows changes since the fork point (like GitHub PR diff). - Debugging: Compare specific ranges to narrow when a bug was introduced.
Code
# ─── Commits on feature not on main ───
git log main..feature --oneline
# E, F
# ─── Commits on main not on feature ───
git log feature..main --oneline
# D
# ─── Symmetric difference ───
git log main...feature --oneline
# D, E, F
# ─── Diff between two tags ───
git diff v1.0..v2.0 --stat
# ─── Diff from fork point (like GitHub PR) ───
git diff main...feature
# ─── Count commits in a range ───
git rev-list --count main..feature
# 2Key Takeaways
A..Bin log = commits in B not in A. In diff = snapshot A vs B.A...Bin log = symmetric difference. In diff = fork point vs B.main..featureis what you'd see in a PR — changes unique to the feature.main...featurediff matches GitHub's PR diff (from merge base).
Interview Prep
-
Q: What is the difference between
A..BandA...Bingit log? A:A..Bshows commits reachable from B but not from A (what B has that A doesn't).A...Bshows commits reachable from either A or B but not both (symmetric difference — what's exclusive to each). -
Q: Why does
git diff A...Bdiffer fromgit diff A..B? A:A..Bdiffs the snapshots at A and B directly.A...Bdiffs the common ancestor of A and B against B — showing only what B introduced since diverging. The...form matches what GitHub shows in PRs. -
Q: How do you count the number of commits a branch is ahead? A:
git rev-list --count main..featurecounts commits onfeaturenot onmain.