How do you make git diff only show the difference between two commits, excluding the other commits in-between?
How do you make git diff only show the difference between two commits, excluding the other commits in-between?
you can simply pass the 2 commits to git diff like :
-> git diff 0da94be 59ff30c > my.patch
-> git apply my.patch
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.
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.
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
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
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
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
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)
$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")
https://github.com/<username>/<reponame>/compare/<commit1>..<commit2>The commit1 and commit2 could be branch-names or commit-hash
For ex:
gs/add-explicit-paths-to-js-files with gs/add-history-helper - https://github.com/twbs/bootstrap/compare/gs/add-explicit-paths-to-js-files..gs/add-history-helper75e09b1c0f5ae5f51078c7a25fe36d892c5cfcfe with 585146a6a7aa70faf25442d7d28636ce57e29588 - https://github.com/twbs/bootstrap/compare/75e09b1c0f5ae5f51078c7a25fe36d892c5cfcfe..585146a6a7aa70faf25442d7d28636ce57e29588Read more in Comparing Commits
Let me introduce easy GUI/idiot proof approach that you can take in these situations.
myRepo_tempmyRepo_original).myRepo_temp and myRepo_original)This is useful for example if you want partially reverse some changes as you can copy stuff from one to another folder.