How to see the changes between two commits without commits in-between?

GitDiff

Git Problem Overview


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

Git Solutions


Solution 1 - Git

you can simply pass the 2 commits to git diff like :

-> git diff 0da94be  59ff30c > my.patch
-> git apply my.patch

Solution 2 - Git

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.

Solution 3 - Git

To compare two git commits 12345 and abcdef as patches one can use the diff command as

diff <(git show 123456) <(git show abcdef)

Solution 4 - Git

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.

Solution 5 - Git

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.

Solution 6 - Git

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

Solution 7 - Git

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

Solution 8 - Git

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

Solution 9 - Git

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.

Solution 10 - Git

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

Solution 11 - Git

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

Solution 12 - Git

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)

Solution 13 - Git

$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")

Solution 14 - Git

To check the diff on GitHub; you can - https://github.com/<username>/<reponame>/compare/<commit1>..<commit2>

Read more in Comparing Commits

Solution 15 - Git

Let me introduce easy GUI/idiot proof approach that you can take in these situations.

  1. Clone another copy of your repo to new folder, for example myRepo_temp
  2. Checkout the commit/branch that you would like to compare with commit in your original repo (myRepo_original).
  3. Now you can use diff tools, (like Beyond Compare etc.) with these two folders (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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser146069View Question on Stackoverflow
Solution 1 - GitOneOfOneView Answer on Stackoverflow
Solution 2 - GitbdonlanView Answer on Stackoverflow
Solution 3 - GitplxView Answer on Stackoverflow
Solution 4 - GitroadevView Answer on Stackoverflow
Solution 5 - Gitbit_cracker007View Answer on Stackoverflow
Solution 6 - GitJuanpaView Answer on Stackoverflow
Solution 7 - GitTomáš DivišView Answer on Stackoverflow
Solution 8 - GitWilliam PursellView Answer on Stackoverflow
Solution 9 - GitFlow OverstackView Answer on Stackoverflow
Solution 10 - GitdengST30View Answer on Stackoverflow
Solution 11 - GitJinmiao LuoView Answer on Stackoverflow
Solution 12 - GitJacob AbrahamView Answer on Stackoverflow
Solution 13 - GitBharath T SView Answer on Stackoverflow
Solution 14 - GitAakashView Answer on Stackoverflow
Solution 15 - GitTine M.View Answer on Stackoverflow