How do you make git diff
only show the difference between two commits, excluding the other commits in-between?

- 8,084
- 8
- 48
- 62
-
19"git diff" **always** show the difference between two commits (or commit and working directory, etc.). – Jakub Narębski Jul 28 '09 at 06:48
-
41@JakubNarębski, he is asking how to see the difference between the changes introduced by one command and the changes introduced by another commit. In other words, the diff of diffs or interdiff. – psusi Sep 04 '15 at 17:50
-
1and if you add --dirstat=files parameter to the diff command, you will take a very nice screenshot on the exact projects and files that are changed, together with a change percentage. Like this: git diff [commit-number] [commit-number] --dirstat=files – Óscar Ibáñez Fernández Jan 03 '17 at 14:53
-
1This question would be clearer if you could add sample git history ascii art and explain which commits you want to diff / exclude from that graph exactly. – Thomas Guyot-Sionnest Sep 24 '20 at 12:43
-
This may directly answer your question but try using Meld or kdiff3 or someother graphical tool – ambassallo Nov 28 '20 at 11:08
-
@JakubNarębski as per the documentation, the default is to "show changes between the working tree and the index", not two commits – simpleuser Jan 19 '22 at 21:05
-
@simpleuser I meant the "git diff" command in general, not specifically `git diff` without any parameters; anyway the important part is that "git diff" is always about two endpoints, and _always_ skips commits in-between. – Jakub Narębski Jan 21 '22 at 14:05
-
I believe this question suffers from an ambiguity of wording: does "commit" refer to a snapshot, or the diff between a snapshot and the one before it? @psusi and [plx's answer](https://stackoverflow.com/a/23527631/673991) sees the latter, that an **interdiff** is called for. [OneOfOne's answer](https://stackoverflow.com/a/1191449/673991) interprets the former, a **wide-diff** as it were, and answers the reason I came here. I think the OP meant the interdiff idea but either way the question should be reworded to be less ambiguous. – Bob Stein Nov 30 '22 at 17:48
15 Answers
you can simply pass the 2 commits to git diff like :
-> git diff 0da94be 59ff30c > my.patch
-> git apply my.patch

- 95,033
- 20
- 184
- 185
-
1That worked for me, but now, How can I apply `my.patch` to other branch? – nacho4d Jun 02 '11 at 02:53
-
3@nacho4d: git checkout other-branch && git apply my.patch && git add . && git commit -am "Message" – Felix Rabe Feb 03 '12 at 19:49
-
1The advantage of using git apply vs. patch is you can include renames and some other changes that are specific to git. I like using git format-patch and git am. – Russell Jun 12 '12 at 11:23
-
The downvote is maybe due to your answer got confusing. If I read the OP questios and see your answer, it does more than the needed. Your original answer was fine. – whoan Aug 16 '15 at 21:15
-
118This answer utterly fails to address the question, so I have no idea why it has so many upvotes. The OP is specifically asking how NOT to get the first command you give, and the second has nothing to do with anything. – psusi Sep 04 '15 at 17:51
-
5This answer does not utterly fail to answer anything. It works perfectly. If you branch off the later of the two commits in question, then apply this diff to that new branch, you will see the changes between the two commits without headache of the intermittent commits. – Craig Labenz Oct 29 '15 at 22:00
-
1@OneOfOne How can do such this, BUT include commits in between? Means I have a commit (first commit), and too many commits and the latest one (last commit), I want to send my changes to someone that is in first situation. – Dr.jacky Nov 17 '16 at 05:39
-
2@Mr.Hyde I'm not sure I completely understand, using that will include all the changes between 2 commits. – OneOfOne Nov 17 '16 at 18:48
-
@OneOfOne Cause question says "excluding the other commits in-between". I think your answer is about just add changes in latest commit over first commit. But you says your command add all of changes over first commit; Am I right? – Dr.jacky Nov 19 '16 at 09:45
-
@OneOfOne Does the order of inputs important? Means the latest commit should become as second parameter. – Dr.jacky Nov 21 '16 at 06:02
-
The question is undefined. And the answer allows to combine any differences, in any order. Upvoting. – Gangnus Feb 26 '18 at 20:58
-
-
@psusi Upvoting just means "*This answer is useful.*". You can confirm it by hovering the mouse cursor over the upvote button. So clicking the button just because "this answer is useful TO ME" is still sensible. For me, I googled "compare two commits" and found this page at the third result and thought this answer was helpful. (I don't upvote the answer for another reason, though.) – ynn Jun 03 '20 at 19:24
-
1@ynn So if I just added all git commands here that would be helpful too?! Answer should be helpful in context. – Farid Jun 30 '22 at 05:18
Asking for the difference /between/ two commits without including the commits in-between makes little sense. Commits are just snapshots of the contents of the repository; asking for the difference between two necessarily includes them. So the question then is, what are you really looking for?
As William suggested, cherry-picking can give you the delta of a single commit rebased on top of another. That is:
$ git checkout 012345
$ git cherry-pick -n abcdef
$ git diff --cached
This takes commit 'abcdef', compares it to its immediate ancestor, then applies that difference on top of '012345'. This new difference is then shown - the only change is the context comes from '012345' rather than 'abcdef's immediate ancestor. Of course, you may get conflicts and etc, so it's not a very useful process in most cases.
If you're just interested in abcdef itself, you can do:
$ git log -u -1 abcdef
This compares abcdef to its immediate ancestor, alone, and is usually what you want.
And of course
$ git diff 012345..abcdef
gives you all differences between those two commits.
It would help to get a better idea of what you're trying to achieve - as I mentioned, asking for the difference between two commits without what's in between doesn't actually make sense.

- 224,562
- 31
- 268
- 324
-
57I will agree that, in general, it doesn't make much sense to compare two commits. But git is really good at not telling you how you should think. Suppose you have two branches, each with distinct commits that look like they are making the same changes to the same sets of files. I would like to be able to use git to tell me if these two patches are the same without having to trust my eyes. I think there IS utility in this. – Chris Cleeland Aug 22 '12 at 22:10
-
9@ChrisCleeland, the interdiff utility can come in handy in that case. Use git diff to get the diff of each commit against its immediate parent, then use interdiff to compare the diffs. – bdonlan Aug 23 '12 at 06:41
-
interdiff would certainly work. Since git already stores patches, it doesn't seem like it would be that hard to compare patch content to patch content rather than comparing hashes. – Chris Cleeland Aug 23 '12 at 14:28
-
3@ChrisCleeland, git does not store patches. It stores file contents. It does have a compression scheme that uses deltas, but the delta sources aren't necessarily correlated with the actual history of the files. – bdonlan Aug 24 '12 at 02:44
-
21The diff between the two commits excluding other commits on their respective branches makes perfect sense: one commit was cherry picked from the other, but may have some subtle differences. You want to see what they are without being cluttered with all of the other unrelated crap that is different between the two branches. – psusi Sep 04 '15 at 17:53
-
4Or say you rebase master onto a feature branch, and must resolve conflicts. Afterwards comparing `origin/featurebranch#HEAD` to `local/featurebranch#HEAD` can help you ensure you didn't muck anything during conflict-resolution. – lefnire Feb 26 '16 at 20:23
-
Or when you've got a fork of a repo and want to see what has changed since you last merged from it, but the repo has hudnreds of commits since then, many on the same files that may undo what a previous commit does. If you prefer only fast-forward merges, there's no way to do the merge and then cancel it. Just doing a diff between where your fork is at and where the upstream repo is at gives you a nice view of what has changed before you do the merge. – aggieNick02 Mar 11 '21 at 19:10
-
@psusi -remembering that "a commit" is a complete list of evert file in the repository and a pointer to the content at a specific point in time. So looking at 2 commits are looking at two different points in time. It does not look specifically at any of the intermediate points in time (unlike other systems which might walk a diff tree of incremental delta). Therefore if something started as "x=1" and ended as "x=99" you sill see that as one change, but have no indication of which commit that change was made or if there were other calues assigned to x during different commits... – David V. Corbin Mar 24 '23 at 11:06
To compare two git commits 12345 and abcdef as patches one can use the diff command as
diff -u <(git show 123456) <(git show abcdef)

- 3,837
- 1
- 36
- 46

- 1,656
- 1
- 12
- 13
-
8
-
7@OneOfOne `git diff <(git show 123456) <(git show abcdef)` doesn't work; `diff <(...) <(...)` does. (I just tried it). – Menachem Dec 09 '15 at 17:39
-
-
24@OneOfOne That doesn't do the same thing. What you suggested would compare the **trees** of each commit, showing a _single patch_. What I (and @plexoos) are doing are comparing _two patches_, each having been introduced by separate commits - in other words, `diff`ing the output from two `diff`s. This involves reading and comparing two input streams. `diff` (GNU, or Unix, `diff`) can do that, while `git diff` cannot. Some may wonder why one would want to do that. I am in the middle of doing that right now, cleaning up a merge that went bad. – Menachem Dec 10 '15 at 21:20
-
2
-
1@joel — yes but there's just a little bit metadata, in my case just one line with a commit id (assuming author name and commit message is the same). Takes half a second to ignore it, and see that the changes introduced by `123456` and `abcdef` are identical. — However if the different patches `123456` and `abcdef` got applied to "very" different source trees, with line numbers, maybe file names, being different — then there's a little bit more metadata that will be different. Still, takes just two or three seconds to ignore such metadata. – KajMagnus Aug 03 '20 at 04:52
-
7
git diff <a-commit> <another-commit> path
Example:
git diff commit1 commit2 config/routes.rb
It shows the difference on that file between those commits.

- 1,002
- 9
- 16
For checking complete changes:
git diff <commit_Id_1> <commit_Id_2>
For checking only the changed/added/deleted files:
git diff <commit_Id_1> <commit_Id_2> --name-only
NOTE: For checking diff without commit in between, you don't need to put the commit ids.

- 2,341
- 1
- 26
- 26
Let's say you have this
A
|
B A0
| |
C D
\ /
|
...
And you want to make sure that A
is the same as A0
.
This will do the trick:
$ git diff B A > B-A.diff
$ git diff D A0 > D-A0.diff
$ diff B-A.diff D-A0.diff

- 667
- 6
- 8
-
5Can also be shortened as a one-liner just as the answer by [@plexoos](https://stackoverflow.com/a/23527631/3009574): ```diff <(git diff B A) <(git diff D A0)``` (same result as with git show) – pogosama Sep 07 '17 at 10:16
-
3
-
Since Git 2.19, you can simply use:
git range-diff rev1...rev2
- compare two commit trees, starting by their common ancestor
or
git range-diff rev1~..rev1 rev2~..rev2
- compare of changes introduced by 2 given commits

- 23
- 4

- 906
- 8
- 9
-
Works even with stash. Just create a small shell wrapper and it will be easy to use. – Et7f3XIV Sep 23 '22 at 02:20
Suppose you want to see the difference between commits 012345 and abcdef. The following should do what you want:
$ git checkout 012345 $ git cherry-pick -n abcdef $ git diff --cached

- 204,365
- 48
- 270
- 300
-
Thanks, that's a good idea to check your result after squashing commits. For example you can checkout your branch with non-squashed commits and cherry pick your squashed commit to see if everything went smooth with the interactive rebase. Additionally when master has went ahead of the branch. – akostadinov Aug 15 '13 at 20:16
To check the diff directly on GitHub; you can - https://github.com/<username>/<reponame>/compare/<commit1>..<commit2>
The commit1
and commit2
could be branch-names or commit-hash
For ex:
- compares branch
gs/add-explicit-paths-to-js-files
withgs/add-history-helper
- https://github.com/twbs/bootstrap/compare/gs/add-explicit-paths-to-js-files..gs/add-history-helper - compares commit
75e09b1c0f5ae5f51078c7a25fe36d892c5cfcfe
with585146a6a7aa70faf25442d7d28636ce57e29588
- https://github.com/twbs/bootstrap/compare/75e09b1c0f5ae5f51078c7a25fe36d892c5cfcfe..585146a6a7aa70faf25442d7d28636ce57e29588
Read more in Comparing Commits

- 21,375
- 7
- 100
- 81
What about this:
git diff abcdef 123456 | less
It's handy to just pipe it to less if you want to compare many different diffs on the fly.

- 149
- 1
- 8
$git log
commit-1(new/latest/recent commit)
commit-2
commit-3
commit-4
*
*
commit-n(first commit)
$git diff commit-2 commit-1
display's all changes between commit-2 to commit-1 (patch of commit-1 alone & equivalent to
git diff HEAD~1 HEAD
)
similarly $git diff commit-4 commit-1
display's all changes between commit-4 to commit-1 (patch of commit-1, commit-2 & commit-3 together. Equivalent to
git diff HEAD~3 HEAD
)
$git diff commit-1 commit-2
By changing order commit ID's it is possible to get
revert patch
. ("$git diff commit-1 commit-2 > revert_patch_of_commit-1.diff")

- 787
- 6
- 6
My alias
settings in ~/.bashrc
file for git diff
:
alias gdca='git diff --cached' # diff between your staged file and the last commit
alias gdcc='git diff HEAD{,^}' # diff between your latest two commits

- 5,989
- 1
- 29
- 45

- 143
- 1
- 5
I wrote a script which displays diff between two commits, works well on Ubuntu.
https://gist.github.com/jacobabrahamb4/a60624d6274ece7a0bd2d141b53407bc
#!/usr/bin/env python
import sys, subprocess, os
TOOLS = ['bcompare', 'meld']
def getTool():
for tool in TOOLS:
try:
out = subprocess.check_output(['which', tool]).strip()
if tool in out:
return tool
except subprocess.CalledProcessError:
pass
return None
def printUsageAndExit():
print 'Usage: python bdiff.py <project> <commit_one> <commit_two>'
print 'Example: python bdiff.py <project> 0 1'
print 'Example: python bdiff.py <project> fhejk7fe d78ewg9we'
print 'Example: python bdiff.py <project> 0 d78ewg9we'
sys.exit(0)
def getCommitIds(name, first, second):
commit1 = None
commit2 = None
try:
first_index = int(first) - 1
second_index = int(second) - 1
if int(first) < 0 or int(second) < 0:
print "Cannot handle negative values: "
sys.exit(0)
logs = subprocess.check_output(['git', '-C', name, 'log', '--oneline', '--reverse']).split('\n')
if first_index >= 0:
commit1 = logs[first_index].split(' ')[0]
if second_index >= 0:
commit2 = logs[second_index].split(' ')[0]
except ValueError:
if first != '0':
commit1 = first
if second != '0':
commit2 = second
return commit1, commit2
def validateCommitIds(name, commit1, commit2):
if commit1 == None and commit2 == None:
print "Nothing to do, exit!"
return False
try:
if commit1 != None:
subprocess.check_output(['git', '-C', name, 'cat-file', '-t', commit1]).strip()
if commit2 != None:
subprocess.check_output(['git', '-C', name, 'cat-file', '-t', commit2]).strip()
except subprocess.CalledProcessError:
return False
return True
def cleanup(commit1, commit2):
subprocess.check_output(['rm', '-rf', '/tmp/'+(commit1 if commit1 != None else '0'), '/tmp/'+(commit2 if commit2 != None else '0')])
def checkoutCommit(name, commit):
if commit != None:
subprocess.check_output(['git', 'clone', name, '/tmp/'+commit])
subprocess.check_output(['git', '-C', '/tmp/'+commit, 'checkout', commit])
else:
subprocess.check_output(['mkdir', '/tmp/0'])
def compare(tool, commit1, commit2):
subprocess.check_output([tool, '/tmp/'+(commit1 if commit1 != None else '0'), '/tmp/'+(commit2 if commit2 != None else '0')])
if __name__=='__main__':
tool = getTool()
if tool == None:
print "No GUI diff tools"
sys.exit(0)
if len(sys.argv) != 4:
printUsageAndExit()
name, first, second = None, 0, 0
try:
name, first, second = sys.argv[1], sys.argv[2], sys.argv[3]
except IndexError:
printUsageAndExit()
commit1, commit2 = getCommitIds(name, first, second)
if not validateCommitIds(name, commit1, commit2):
sys.exit(0)
cleanup(commit1, commit2)
checkoutCommit(name, commit1)
checkoutCommit(name, commit2)
try:
compare(tool, commit1, commit2)
except KeyboardInterrupt:
pass
finally:
cleanup(commit1, commit2)
sys.exit(0)

- 915
- 9
- 8
My alias
settings in ~/.zshrc
file for git diff
:
alias gdf='git diff HEAD{'^',}' # diff between your recent tow commits
Thanks @Jinmiao Luo
git diff HEAD~2 HEAD
complete change between latest 2nd commit and current.
HEAD
is convenient

- 3,643
- 24
- 25
Let me introduce easy GUI/idiot proof approach that you can take in these situations.
- Clone another copy of your repo to new folder, for example
myRepo_temp
- Checkout the commit/branch that you would like to compare with commit in your original repo (
myRepo_original
). - Now you can use diff tools, (like Beyond Compare etc.) with these two folders (
myRepo_temp
andmyRepo_original
)
This is useful for example if you want partially reverse some changes as you can copy stuff from one to another folder.

- 418
- 6
- 10