假设我在git中有一个名为filex.code
的文件,我希望看到该文件的最后x
个版本的完整代码,其中每个都已更改部分突出显示 - 所有在一个地方。因此,x
- filex.code
的托管提交历史记录,几乎就像我正在执行x
- 条件差异,但查看历史版本而不是从不同分支合并。
x
越大越好。 Crossplatform会很棒,但三巨头中的任何一个都可以。能够编辑最新版本也会很棒,但只读可视化就足够了。
请注意,这与提交到文件的simple history不同,所以其他非常棒的gitk path/to/file
(或者您喜欢的SourceTree或任何可视化的git客户端)并不是我想要的。 git log -p
也很接近,它的输出很诱人地包含了我想要的所有信息,只是它是一个线性的,几乎是“程序”的输出格式,而不是一个好的,相对非等级的,视觉上的,如你的最喜欢的三层GUI'd mergetool。
(编辑:另一个非常酷的选项,最终仍然会遇到仅显示每行最新来源和线性输出的缺点git blame
,但它很酷。)
所以我也不是在寻找setting up difftool,我不这么认为。我希望将x
次历史编辑迭代可视化为单个文件,而不是将文件的两个已知版本区分开来。
问太多了?这是WTFA(写出“神奇”App [你自己])的情况吗?
较小的替代方案:是否有一个三层合并工具,我可以欺骗显示单个文件的最后三个提交?
答案 0 :(得分:3)
此脚本并排打开文件的最后N个版本。
#!/usr/bin/env python
import os, sys, tempfile
from shutil import rmtree
from subprocess import call, Popen, PIPE
from optparse import OptionParser
from traceback import print_exc
COMMAND = 'vim -d'
def vcall(cmd, **kwargs):
if options.verbose:
print ' '.join(cmd)
return call(' '.join(cmd) if sys.platform == 'darwin' else cmd,
**kwargs)
parser = OptionParser('usage: %s [-n <number of revisions>] filename' %
sys.argv[0])
parser.add_option('-n', '--num', dest='N', type='int',
help='number of revisions', default=3)
parser.add_option('-v', '--verbose', dest='verbose',
help='be verbose', default=False, action='store_true')
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error('incorrect number of arguments')
filename = args[0]
if vcall('git rev-parse'.split()) != 0:
sys.exit(1)
try:
cmd = 'git rev-list HEAD --'.split() + [filename]
if options.verbose:
print ' '.join(cmd)
pipe = Popen(' '.join(cmd) if sys.platform == 'darwin' else cmd,
stdout=PIPE).stdout
revs = []
for i, line in enumerate(pipe):
if i == options.N:
break
revs.append(line.rstrip())
except:
print_exc()
N = len(revs)
if N == 0:
sys.exit('fatal: ambiguous argument %s: path not in the working tree' %
filename)
elif N < options.N:
sys.stderr.write('%s has only %d revision%s' %
(filename, N, 's' if N > 1 else ''))
tempdir = ''
try:
tempdir = tempfile.mkdtemp()
head, tail = os.path.split(filename)
tempfiles = []
for i in xrange(N):
tempfiles.append(tail + ('.%d' % i if i else ''))
for i, f in enumerate(tempfiles):
with open(os.sep.join((tempdir, f)), 'w') as fout:
vcall(['git', 'show', '%s:./%s' % (revs[i], filename)], stdout=fout)
vcall(COMMAND.split() + list(reversed(tempfiles)), shell=True, cwd=tempdir)
except:
print_exc()
finally:
try:
if tempdir and os.path.isdir(tempdir):
rmtree(tempdir)
except:
print_exc()
注意:
Vimdiff仅在4个(第一个)缓冲区中突出显示差异的限制,但是并排显示 - 显示所有文件修订(例如N = 20效果很好)。为了避免N> 4的警告,请使用COMMAND = 'vim -O'
并排查看版本而不会有任何差异。
脚本已经变得太大了,不适合SO风格,但它现在非常防弹 - 但对于经验丰富的人来说足够简单。