查看单个文件历史记录的`x`提交的完整文件diff(托管在git中) [英] View full file diff of `x` commits of a single file's history (that's hosted in git)

查看:183
本文介绍了查看单个文件历史记录的`x`提交的完整文件diff(托管在git中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我在git中有一个名为filex.code的文件,我想查看该文件的最新x版本的完整代码,并突出显示每个更改的部分-全部集中在一个地方.因此,x提交的提交历史记录为filex.code,几乎就像我在做x提交的差异报告一样,只是查看历史版本,而不是从不同的分支合并.

Say I have a file in git called filex.code, and I want to see the full code of the last x versions of that file with each changed section highlighted -- all in one place. So an x-paned commit history of filex.code, almost as if I were doing an x-paned diff, but viewing historical versions rather than merging from different branches.

x越大越好.跨平台会很棒,但是任何三大公司都可以.能够编辑最新版本也很棒,但是只读的可视化效果很多.

The greater x, the better. Crossplatform would be great, but any of the Big Three works. Being able to edit the latest version would also be great, but read-only visualization is plenty.

请注意,这不同于提交的简单历史记录到文件,因此原本很棒的 gitk path/to/file (或SourceTree或您喜欢的任何可视git客户端)都不是什么我在找. git log -p 也很接近,它的输出诱人地包含了我想要的所有信息,只是它们全部包含在线性的,几乎程序化"的输出格式,而不是像您最喜欢的三窗格式GUI的mergetool那样的一种良好的,相对没有层次的可视化格式.

Note that this is different from a simple history of commits to a file, so the otherwise wonderful gitk path/to/file (or SourceTree or whatever visual git client you love) isn't what I'm looking for. git log -p also comes close, and its output tantalizingly includes all the information I'd want, just that it's all in a linear, almost "procedural" output format rather than a good, relatively non-hierarchical, visual one like your favorite three-paned GUI'd mergetool's.

(另一个非常酷的选项最终仍然会遇到仅显示每行的最新来源和线性输出的缺点,这是

( Another really cool option that ultimately still experiences the shortcomings of only showing each line's latest source & a linear output is git blame, but it's cool.)

所以我也不是在精确地寻找设置difftool .我不想将文件的两个已知版本进行比较,而是想将历史编辑的x迭代可视化为单个文件.

So I'm not precisely looking for setting up difftool either, I don't think. Rather than diffing two known versions of a file, I want to visualize x iterations of historical edits to a single file.

问太多?这是WTFA(写很棒的"应用程序[您自己])情况吗?

Asking too much? Is this a WTFA (Write The "Fantastic" App [yourself]) situation?

替代方案:是否可以通过三窗格合并工具显示单个文件的最后三个提交?

Lesser alternative: Is there a three-paned mergetool that I can trick into displaying the last three commits of a single file?

推荐答案

此脚本并排打开文件的最后N个修订版本.

This script opens last N revisions of the file side-by-side.

#!/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()

注意:

  1. Vimdiff仅在4个(第一个)缓冲区中突出显示差异,但对于并排显示-显示所有文件修订(例如N = 20效果很好).为避免对N> 4发出警告,请使用COMMAND = 'vim -O'并排查看版本,完全没有任何差异.

  1. Vimdiff has a limitation of highlighting diffs in only 4 (first) buffers, but as for showing side-by-side - all file revisions are shown (eg N=20 works great). To avoid the warning for N>4 use COMMAND = 'vim -O' to see versions side-by-side without any diffs at all.

对于SO风格而言,脚本已经变得太大了,但是现在它已经相当安全了,但对于有经验的眼睛来说却足够简单.

The script has grown to be too large for SO style, but it is quite bullet-proof now - yet simple enough for an experienced eye.

这篇关于查看单个文件历史记录的`x`提交的完整文件diff(托管在git中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆