如何使
git diff
只显示两次提交之间的差异,排除中间的其他提交?
您可以简单地将 2 个提交传递给 git diff,如下所示:
-> git diff 0da94be 59ff30c > my.patch
-> git apply my.patch
询问两个提交之间的差异而不包括中间的提交是没有意义的。提交只是存储库内容的快照;询问两者之间的差异必然包括它们。所以问题是,你真正在寻找什么?
正如 William 所建议的,精挑细选可以为您提供基于另一个提交的单个提交的增量。那就是:
$ 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
为您提供这两个提交之间的所有差异。
这将有助于更好地了解您想要实现的目标 - 正如我所提到的,询问两次提交之间的差异而不考虑其间的差异实际上是没有意义的。
diff -u <(git show 123456) <(git show abcdef)
示例:
git diff commit1 commit2 config/routes.rb
它显示了这些提交之间该文件的差异。
git diff <commit_Id_1> <commit_Id_2>
git diff <commit_Id_1> <commit_Id_2> --name-only
:要检查差异而不需要提交,您不需要输入提交 ID。
A
|
B A0
| |
C D
\ /
|
...
并且您要确保
A
与
A0
相同。 这就能解决问题:
$ git diff B A > B-A.diff
$ git diff D A0 > D-A0.diff
$ diff B-A.diff D-A0.diff
git range-diff rev1...rev2
- 比较两个提交树,从它们的共同祖先开始
或者
git range-diff rev1~..rev1 rev2~..rev2
- 比较 2 个给定提交引入的更改
https://github.com/<username>/<reponame>/compare/<commit1>..<commit2>
commit1
和
commit2
可以是branch-names或commit-hash 例如:
将分支
gs/add-explicit-paths-to-js-files
gs/add-history-helper
进行比较 - https://github.com/twbs/bootstrap/compare/gs/add-explicit-paths-to-js-files..gs/add-history-helper比较提交
75e09b1c0f5ae5f51078c7a25fe36d892c5cfcfe
585146a6a7aa70faf25442d7d28636ce57e29588
- https://github.com/twbs/bootstrap/compare/75e09b1c0f5ae5f51078c7a25fe36d892c5cfcfe..585146a6a7aa70faf25442d7d28636ce57e2 9588
$ git 结账 012345 $ gitcherry-pick-n abcdef $ git diff --缓存
git diff abcdef 123456 | less
如果您想即时比较许多不同的差异,只需将其通过管道传输到 less 就很方便。
alias
文件中
~/.bashrc
的我的 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
commit-1(new/latest/recent commit)
commit-2
commit-3
commit-4
*
*
commit-n(first commit)
显示 commit-2 到 commit-1 之间的所有更改(仅 commit-1 的补丁且相当于
git diff HEAD~1 HEAD
)
同样
$git diff commit-4 commit-1
显示 commit-4 到 commit-1 之间的所有更改(commit-1 的补丁, commit-2 和 commit-3 一起。相当于git diff HEAD~3 HEAD
)
$git diff commit-1 commit-2
通过更改订单提交 ID,可以获得
revert patch
。 (“$git diff commit-1 commit-2 > revert_patch_of_commit-1.diff”)
#!/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)
alias
文件中
~/.zshrc
的我的 git diff
设置:alias gdf='git diff HEAD{'^',}' # diff between your recent tow commits
谢谢 @罗金淼
git diff HEAD~2 HEAD
最新第二次提交与当前提交之间的完整更改。
HEAD
很方便
将存储库的另一个副本克隆到新文件夹,例如
myRepo_temp
myRepo_original
myRepo_temp
myRepo_original
)使用差异工具(例如Beyond Compare等)