View full file diff `x` captures one file history (hosted in git)

Let's say I have a file in git called filex.code , and I want to see the full code of the last x versions of this file with each sector selected, all in one place. So, x last history of fixing filex.code , almost the same as if I were executing an x written diff, but looking through historical versions, rather than merging from different branches.

The larger the x , the better. Crossplatform will be great, but any of the Big Three works. The ability to edit the latest version will also be great, but there are a lot of read-only visualizations.

Please note that this is different from a simple file commit history , so otherwise gitk path/to/file (or SourceTree or any git visual client you like) is great, not what I'm looking for. git log -p also close, and its output painfully includes all the information I would like, just to have it all in a linear, almost "procedural" output format, and not a good, relatively non-hierarchical, visual one like your favorite three-layer GUI'd mergetool.

( Edit: Another really cool option, which ultimately still suffers from flaws showing only every line of the last source and git blame linear output, but that's cool.)

So I'm definitely not looking for a diffftool setting , I don't think so. Instead of distinguishing between two known versions of a file, I want to visualize x iterations of historical changes in a single file.

To ask too much? Is it a WTFA (write a โ€œfantasticโ€ application [yourself])?

Smaller alternative: is there a three-layer mergetool that I can fool to display the last three commits of a single file?

+4
source share
1 answer

This script opens the last N file fixes 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() 

Notes:

  • Vimdiff has the restriction of highlighting differences in only 4 (first) buffers, but for showing side by side - all file changes are displayed (for example, N = 20 works fine). To avoid the warning for N> 4, use COMMAND = 'vim -O' to see versions side by side without any differences.

  • The script has become too big for the SO style, but now it's pretty bulletproof, but simple enough for an experienced eye.

+3
source

All Articles