如何在没有提交的情况下查看两次提交之间的更改?

如何使git diff只显示两次提交之间的差异,不包括中间的其他提交?

787293 次浏览

您可以简单地将2个提交传递给git diff,例如:

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

假设您想查看提交012345和abcdef之间的区别。以下应该可以完成您想要的操作:

$ git checkout 012345$ git cherry-pick -n abcdef$ git diff --cached

询问 /between/两次提交的区别而不包括中间的提交是没有意义的。提交只是存储库内容的快照;询问两次提交之间的区别必然包括它们。所以问题是,你真正在寻找什么?

正如William所建议的,樱桃采摘可以给你一个提交的delta重新基于另一个提交的顶部。那就是:

$ git checkout 012345$ git cherry-pick -n abcdef$ git diff --cached

这需要提交'abcdef',将其与其直接祖先进行比较,然后在'012345'之上应用这种差异。然后显示这个新的差异-唯一的变化是上下文来自'012345'而不是'abcdef的直接祖先。当然,你可能会遇到冲突等,所以在大多数情况下这不是一个非常有用的过程。

如果你只是对abcdef本身感兴趣,你可以这样做:

$ git log -u -1 abcdef

这将abcdef与其直接祖先进行比较,并且通常是您想要的。

当然还有

$ git diff 012345..abcdef

给出这两个提交之间的所有差异。

这将有助于更好地了解你想要实现的目标——正如我所提到的,询问两次提交之间的差异而不知道两者之间的区别实际上是没有意义的。

要比较两个git提交12345和abcdef作为补丁,可以使用diff命令作为

diff <(git show 123456) <(git show abcdef)
git diff <a-commit> <another-commit> path

示例:

git diff commit1 commit2 config/routes.rb

它显示了这些提交之间在该文件上的差异。

这个怎么样:

git diff abcdef 123456 | less

如果你想在飞行中比较许多不同的差异,只需将其管道减少是很方便的。

假设你有这个

A|B    A0|    |C    D\   /|...

你要确保AA0是一样的。

这将做的伎俩:

$ git diff B A > B-A.diff$ git diff D A0 > D-A0.diff$ diff B-A.diff D-A0.diff

我的alias设置在git diff~/.bashrc文件中:

alias gdca='git diff --cached' # diff between your staged file and the last commitalias gdcc='git diff HEAD{,^}' # diff between your latest two commits

我写了一个脚本,显示两个提交之间的差异,在Ubuntu上运行良好。

https://gist.github.com/jacobabrahamb4/a60624d6274ece7a0bd2d141b53407bc

#!/usr/bin/env pythonimport 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 toolexcept subprocess.CalledProcessError:passreturn 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 = Nonecommit2 = Nonetry:first_index = int(first) - 1second_index = int(second) - 1if 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 = firstif second != '0':commit2 = secondreturn commit1, commit2
def validateCommitIds(name, commit1, commit2):if commit1 == None and commit2 == None:print "Nothing to do, exit!"return Falsetry: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 Falsereturn 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, 0try: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:passfinally:cleanup(commit1, commit2)sys.exit(0)

从Git 2.19开始,您可以简单地使用:

git range-diff rev1...rev2-比较两个提交树,从它们的共同祖先开始

git range-diff rev1~..rev1 rev2~..rev2-比较2个给定提交引入的更改

检查完整更改:

  git diff <commit_Id_1> <commit_Id_2>

仅检查更改/添加/删除的文件:

  git diff <commit_Id_1> <commit_Id_2> --name-only

:为了检查diff而不在两者之间提交,您不需要放置提交ID。

我的alias设置在git diff~/.zshrc文件中:

alias gdf='git diff HEAD{'^',}' # diff between your recent tow commits

谢谢@罗金苗


git diff HEAD~2 HEAD

在最近的第二次提交和当前提交之间完成更改。

HEAD很方便

$git log

commit-1(new/latest/recent commit)commit-2commit-3commit-4**commit-n(first commit)

$git diff提交-2提交-1

显示提交-2到提交-1之间的所有更改(仅提交-1的补丁,相当于git diff HEAD~1 HEAD

类似地$git diff的具体实现步骤如下:

显示提交4到提交1之间的所有更改(提交1的补丁,提交-2和提交-3在一起。相当于git diff HEAD~3 HEAD

<强>$git diff提交-1提交-2

通过更改提交ID的顺序,可以获得revert patch。("$git diff bit-1>revert_patch_of_commit-1.diff")

让我介绍一下在这些情况下可以采用的简单GUI/白痴证明方法。

  1. 将存储库的另一个副本克隆到新文件夹,例如myRepo_temp
  2. 签出您希望与原始存储库中的提交进行比较的提交/分支(myRepo_original)。
  3. 现在您可以使用diff工具(如Beyond Compare等)处理这两个文件夹(myRepo_tempmyRepo_original

这是有用的,例如,如果你想部分逆转一些更改,因为你可以将内容从一个文件夹复制到另一个文件夹。

要直接检查github上的差异;您可以-https://github.com/<username>/<reponame>/compare/<commit1>..<commit2>

commit1commit2可能是分支名称默认哈希值

对于前:

阅读更多比较提交