How to see the changes between two commits without commits in-between?
Categories:
Comparing Two Git Commits Without Intermediate Changes

Learn how to effectively use git diff
to compare any two commits in your repository, ignoring all changes that occurred in between them.
When working with Git, it's common to need to compare the state of your codebase between two specific points in history. While git diff
is a powerful command, its default behavior often compares the working directory to a commit, or two consecutive commits. This article focuses on how to get a clean diff between any two arbitrary commits, effectively ignoring all the changes introduced by commits that lie chronologically between them. This is particularly useful for understanding the net impact of a feature branch or comparing different versions of a release.
Understanding Git Diff Basics
Before diving into comparing non-consecutive commits, let's quickly review the fundamental ways git diff
works. By default, git diff
without any arguments shows changes in your working directory that are not yet staged. With one commit, it compares your working directory to that commit. With two commits, it typically compares the first commit to the second. The key is to specify the exact commits you want to compare, ensuring Git understands you're interested in the difference in content between those two snapshots, not the history of how one evolved into the other.
flowchart TD A[Commit A] --> B[Commit B] B --> C[Commit C] C --> D[Commit D] E[Commit E] subgraph "Standard Diff (A..D)" A -- "Changes from A to B" --> B B -- "Changes from B to C" --> C C -- "Changes from C to D" --> D end subgraph "Target Diff (A...D)" A -.-> D end style A fill:#f9f,stroke:#333,stroke-width:2px style D fill:#f9f,stroke:#333,stroke-width:2px style E fill:#ccc,stroke:#333,stroke-width:1px linkStyle 0 stroke-dasharray: 5 5 linkStyle 1 stroke-dasharray: 5 5 linkStyle 2 stroke-dasharray: 5 5 linkStyle 3 stroke-width:3px,fill:none,stroke:red linkStyle 4 stroke-width:3px,fill:none,stroke:red
Visualizing the difference between a standard diff (A..D) and a direct diff (A...D) ignoring intermediate commits.
The Three-Dot (A...B) Syntax for Direct Comparison
The most straightforward and recommended way to compare two arbitrary commits, ignoring intermediate changes, is to use the three-dot ...
syntax with git diff
. This command compares the state of the tree at the second commit (B
) with the common ancestor of both commits (A
and B
). However, if you want to compare the content of commit A
directly to the content of commit B
, you simply specify them directly without any range operators.
git diff <commit-A-hash> <commit-B-hash>
Directly comparing the content of two specific commits.
Let's break this down:
<commit-A-hash>
: This is the identifier for the first commit you want to compare. This could be a full SHA-1 hash, a short hash, a branch name, a tag, orHEAD~N
.<commit-B-hash>
: This is the identifier for the second commit you want to compare. Git will show you what changes are needed to transform the state of<commit-A-hash>
into the state of<commit-B-hash>
.
git log --oneline
to easily find the short hashes of the commits you want to compare. For example, git log --oneline --graph
provides a visual history.Practical Example
Imagine you have a main
branch and a feature/new-ui
branch. You want to see the net changes introduced by feature/new-ui
since it diverged from main
, but without merging it yet. You can find the merge base (the common ancestor) and then compare your feature branch head to that merge base. However, if you just want to compare the current state of main
to the current state of feature/new-ui
, regardless of their history, the direct comparison is what you need.
# First, identify the commits you want to compare
# Let's say 'main' is at commit 'abcdef1' and 'feature/new-ui' is at '1234567'
# To compare the current state of 'main' to the current state of 'feature/new-ui':
git diff main feature/new-ui
# Alternatively, using full or short hashes:
git diff abcdef1 1234567
# To see the diff in a specific file:
git diff main feature/new-ui -- path/to/your/file.js
Examples of using git diff
to compare two branch heads or specific commit hashes.
git diff <commit-A> <commit-B>
shows you the changes that would need to be applied to the tree of <commit-A>
to make it identical to the tree of <commit-B>
. This is a pure content comparison, ignoring the commit history between them.Comparing with the Merge Base (Two-Dot vs. Three-Dot Revisited)
While the direct comparison (git diff <commit-A> <commit-B>
) is what the question asks for, it's important to distinguish it from the git diff A...B
(three-dot) syntax, which is also very useful for comparing branches. The three-dot syntax compares the second commit (B
) with the merge base of A
and B
. This effectively shows you what changes B
introduced since it diverged from A.
# Find the common ancestor (merge base) of two branches
MERGE_BASE=$(git merge-base main feature/new-ui)
# Compare the feature branch to its merge base with main
git diff $MERGE_BASE feature/new-ui
# This is equivalent to the three-dot syntax:
git diff main...feature/new-ui
Comparing a branch to its common ancestor with another branch using git merge-base
or the three-dot syntax.
The choice between git diff <commit-A> <commit-B>
and git diff A...B
depends on your intent:
git diff <commit-A> <commit-B>
: Shows the literal content difference between the two specified commits, ignoring any history. This is what you use when you want to see the 'final state' difference.git diff A...B
: Shows the changes introduced on branchB
since it diverged from branchA
. This is useful for code review or understanding the unique contributions of a feature branch.
git difftool
which can integrate with external diff viewers like Beyond Compare, Meld, or VS Code.