4

git に というファイルがあり、そのファイルの最新バージョンの完全なコードを、変更された各セクションが強調表示された状態ですべて 1 か所でfilex.code確認したいとします。そのため、 のコミット履歴は、ほとんどdiff を実行しているように見えますが、異なるブランチからマージするのではなく、履歴バージョンを表示しています。xxfilex.codex

大きいほどx良い。クロスプラットフォームは素晴らしいですが、ビッグ 3 はどれも機能します。最新バージョンを編集できることも素晴らしいことですが、読み取り専用の視覚化で十分です。

これはファイルへのコミットの単純な履歴とは異なることに注意してください。そのため、それ以外の場合は素晴らしいgitk path/to/file(または SourceTree または好きなビジュアル git クライアント) は、私が探しているものではありません。 git log -pまた、その出力には、私が望むすべての情報が興味をそそるほど含まれています。お気に入りの3ペインGUIのような、比較的非階層的で視覚的なものではなく、線形でほぼ「手続き型」の出力形式になっているだけです。 'd mergetool's.

編集:各行の最新のソースと線形出力のみを表示するという欠点を最終的に経験するもう1つの本当にクールなオプションは ですがgit blame、クールです。)

だから私はdifftoolのセットアップを正確に探しているわけではありません。xファイルの既知の 2 つのバージョンを比較するのではなく、過去の編集の反復を 1 つのファイルに視覚化したいと考えています。

求めすぎ?これは WTFA (「ファンタスティック」アプリ [自分で] を書く) の状況ですか?

より少ない選択肢: 1 つのファイルの最後の 3 つのコミットを表示するように騙すことができる 3 ペインのマージツールはありますか?

4

1 に答える 1

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()

ノート:

  1. Vimdiff には 4 つの (最初の) バッファーのみで差分を強調表示するという制限がありますが、並べて表示する場合は、すべてのファイル リビジョンが表示されます (たとえば、N=20 はうまく機能します)。N>4 の警告を回避するCOMMAND = 'vim -O'には、差分をまったく表示せずにバージョンを並べて表示します。

  2. スクリプトは SO スタイルには大きくなりすぎましたが、今では非常に防弾です - それでも経験豊富な目にとっては十分に単純です。

于 2012-07-31T07:17:04.593 に答える