compare branches git is the Git CLI operation using git diff and git log to display file-level diffs and commit history differences between two branches.
# Show file changes between the tips of two branches (two-dot)
git diff <branch1>..<branch2>
# Show changes that occurred on branch2 since it diverged from branch1 (three-dot)
git diff <branch1>...<branch2>
# Equivalent to two-dot using space
git diff <branch1> <branch2>
# List commits present in branch2 but not in branch1
git log <branch1>..<branch2>
# Same with oneline summary
git log --oneline <branch1>..<branch2>
# Compare a single file between two branches
git diff <branch1>..<branch2> -- <filepath>
Syntax Reference
The core command structure for comparing two branches relies on git diff and git log with double-dot (..), triple-dot (...), or space-separated references. Double-dot compares the tips directly. Triple-dot finds the merge base and compares against that, revealing only the changes on the second branch since divergence.
Rapid Reference Cheat Sheet
| Action | CLI Command | Notation | Key Flag | Result |
|---|---|---|---|---|
| Compare file content (tips) | git diff main..feature |
.. |
N/A | Unified diff of all file changes between branch tips |
| Compare file content (since divergence) | git diff main...feature |
... |
N/A | Diff of changes on feature only, ignoring common ancestor state |
| List commits not in main | git log main..feature |
.. |
--oneline |
Compact commit list (one per line) |
| Compare a specific file | git diff main..feature -- src/app.js |
.. |
-- <path> |
Diff only for the given file |
| List changed file names only | git diff --name-only main..feature |
.. |
--name-only |
Paths of files that differ |
Notation Comparison
- Space (
git diff A B): Equivalent to double-dot. Compares the tips of both branches. Shows changes from A to B. Useful when both branches have diverged and you want the total diff. - Double-dot (
A..B): Same as space forgit diff. Forgit log, shows commits reachable from B but not from A. The canonical way to see what B has that A doesn’t. - Triple-dot (
A...B): Forgit diff, finds the merge-base of A and B, then diffs that base against B. Shows only the changes introduced on branch B since it branched off A. Forgit log, shows commits reachable from either A or B but not from both.
Key Flags from Verified Context
--oneline: Compresses each commit to a single line (hash + subject). Essential for quick scan.--name-only: Forgit diff, shows only file paths, no patch content. Ideal for inventory.--all: Forgit branchwhen listing local and remote branches.- File path: Append — <path> after the branch specifiers to narrow to a subtree.
Typical Workflow Pattern
# 1. Quick overview of what's in feature but not in main
git log --oneline main..feature
# 2. See the actual code modifications since branching
git diff main...feature
# 3. Check if any changes conflict with main's latest
git diff main..feature
# 4. Focus on one file's changes
git diff main..feature -- config/database.yml
Error Resolution & Troubleshooting
| Error Code / Message | Root Cause | Remediation Command |
|---|---|---|
fatal: ambiguous argument 'main..feature': unknown revision or path not in the working tree |
Typo in branch name or branch not fetched locally. The reference does not exist as a ref. | git branch -a to list all local and remote branches; correct the spelling. |
fatal: bad revision 'main..feature' |
One of the branches is missing (e.g., detached HEAD). Use git rev-parse --symbolic-full-name HEAD to verify current ref. |
git branch feature <hash> if the commit exists but has no branch; then retry diff. |
diff: ... no changes found (empty diff) |
Branches are at the same commit (fast-forward or identical). | Verify with git merge-base --is-ancestor main feature; echo $?. No action needed. |
| Partial diff: only some files shown | Uncommitted changes in working tree are not included. git diff only compares committed states. |
Stage all changes with git add -A and git stash, then run diff again, or use git diff with HEAD vs branch. |
Production-Grade Implementation
In CI/CD pipelines or daily review workflows, standardize branch comparison to avoid human error. Follow these practices:
- Always use triple-dot for feature branch diffs –
git diff $BASE...$HEAD. This shows only the changes introduced by the feature branch, ignoring changes that happened in$BASEafter branching. - Automate pre-merge checks – In GitHub Actions or GitLab CI, run
git log --oneline origin/main..HEADto list commits that will be merged. Fail the pipeline if the count exceeds a threshold (e.g., 20 commits) to enforce small, regular merges. - Use
--name-onlyin scripts – When you need to trigger tests for changed modules, capturegit diff --name-only origin/main...HEADand feed it to a dependency analyzer. Reduces test execution time. - Guard against stale bases – Before comparing, ensure the target branch is up-to-date. Run
git fetch --prune originfirst. This prevents comparing against an outdatedorigin/main.
Verified References
| Command | Source | Notes |
|---|---|---|
git diff |
manpages.ubuntu.com | This form is to view the changes you have in your working tree relative to the named . You can use HEAD to compare it with the latest commit, or a branch name t |
git log |
manpages.ubuntu.com | Several things can prevent that information being available to display. When git-annex-forget is used, old historical data gets cleared from the branch. |
Frequently Asked Questions
What is the difference between `git diff branch1 branch2` and `git log branch1..branch2`?
Answer: `git diff` shows line-level file changes; `git log` lists commit history differences.
`git diff <branch1> <branch2>` outputs a unified diff of all changes between the branch tips. `git log <branch1>..<branch2>` displays commits present in branch2 but not in branch1. For a symmetric difference (commits unique to each branch), use `git log <branch1>…<branch2>`.
# Quick comparison:
git diff main feature-x
git log --oneline main..feature-x
How do I fix the error ‘fatal: ambiguous argument’ when comparing branches in Git?
Answer: Fix by checking branch name spelling, using full refs (refs/heads/branch), or separating branch names from paths with --.
Ambiguous argument errors occur when a branch name matches a file or tag. Use git diff <branch> -- <path> to disambiguate. Alternatively, prefix with heads/ or origin/ for remote branches.
# Resolve ambiguity:
git diff main -- myfile.txt
git diff refs/heads/main refs/heads/feature-x
What is the fastest way to compare only diverged commits between two branches in Git?
Answer: Use git log --oneline branch1...branch2.
The three-dot symmetric difference yields a union of commits not reachable from both branches. For remote tracking, use origin/branch. Add --left-right to mark commit sides with `<` or `>`.
# Fastest diverged commit list:
git log --oneline --no-merges main...feature-x
# With side indicators:
git log --oneline --left-right main...feature-x

Command Line Expert & Software Engineer
Welcome! I’m Thomas Heinrich, a software engineer and system administrator with a deep passion for the Command Line Interface (CLI). With years of experience navigating the terminal, building backend architectures, and automating server deployments, I created this space to share practical, real-world terminal knowledge.
Whether you are a beginner taking your first steps in a Linux environment or a seasoned DevOps engineer looking to optimize your deployment scripts, you will find actionable solutions here. My goal is to help you ditch the mouse, speed up your workflow, and harness the full power of the command line.