View full file diff of `x` commits of a single file's history (that's hosted in git)
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 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.
- git - set KDiff3 as default mergetool
- git tells me that I Merge conflict, but also tells me that no files need merging
- Is Git's auto-detection scripted or is it within some Git executable?
- How to use git mergetool's filemerge
- git — how to recover from unfinished merge
- Can I rename LOCAL, REMOTE and BASE as used in git 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.
(Edit: 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.)
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.
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?
One Solution collect form web for “View full file diff of `x` commits of a single file's history (that's hosted in git)”
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) 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 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 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.
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.