2012-02-12 17 views
2

これは語数に関するものですが、リポジトリ内のすべてのgitコミットにまたがってプログラムを実行していると思います。私は執筆プロジェクトをやっていて、それぞれのコミット後にプログラムで単語数を生成したいと思ったのは遅かったです。 texファイルのみ。しかし、その後、プロジェクトの人生のためのカウントを取得する方法は?私はそれを行う簡単な方法を見つけることができなかったので、それは私が求めているものです。リポジトリの履歴で各gitコミットの単語数を見つける方法は?

私のソリューションは、日付や単語がカウントプロジェクトの生活の中でコミット各個人のブランチをチェックアウトし、取得するために私の小さなシェル/ sedの/ Perlスクリプトを実行しているの手動プロセスを自動化することでした

#!/usr/bin/env perl 

use strict; 
use warnings; 
use 5.014; 
use App::gh::Git; 
use IPC::System::Simple qw(capture); 

my $repo = Git->repository(Directory => '/home/amiri/MyProject/.git'); 
my @commits 
    = reverse $repo->command('rev-list', '--all', '--date', 'short'); 

my $command 
    = qq{find /home/amiri/MyProject -name "*.tex" | xargs wc -w | grep total | sed 's/[a-zA-Z[:space:]]//g'}; 

my $command2 
    = q{git log | grep "Date:" | sed -n 1p | perl -pi -e "s/^Date:\s+//g" | perl -pi -e "s/2011 -\d+$/UTC 2011/g"}; 

for my $commit (@commits) { 
    $repo->command("checkout", "-b", "$commit", "$commit"); 
    my $count = capture($command); 
    my $date = capture($command2); 
    chomp $date; 
    say "$date,$count"; 
    $repo->command("checkout", "master"); 
    $repo->command('branch', "-d", $commit); 
} 

これはうまくいきますが、もっと良い方法があると感じています。少し不気味なようです。

+0

あなたはそれをかなり簡単に行うために[この回答](http://stackoverflow.com/a/9141855/635608)を適応させることができます。 (その質問に対する私の答えではなく、それはあなたのアプローチに近く、それほど良いものではありません) – Mat

答えて

3

あなたは実装が簡単に何かをしたかった、と少し次善のと場しのぎであること気にしない場合は、あなたがこれを行うことができます:

for commit in `git rev-list --all`; do 
    git log -n 1 --pretty=%ad $commit 
    git archive $commit | tar -x -O | wc -w 
done 

をこれは、あなたが持っているものよりも道短く、私はそれがかもしれない疑いがあります単語を数えるためにファイルを読み直すだけでファイルをチェックアウトする必要がなくなるため、高速化することもできます。 (特定のファイルだけに、それを制限するには、あなたがgit archiveにそれらをなどの追加の引数を渡すと、指定したgit ls-tree -r --name-only <commit>にコミット内のすべてのファイルのリストを得ることができることに注意することができます。)

git logラインはちょうどコミット日付を印刷します。あなたがもっとやりたいことがあれば、man git-logを見てください。本来、作成者の日付は%ad、コミットの対象は%sなどのようなプレースホルダーがたくさんあります。次の行が作業を行います。 git archiveは、配布用に特定のツリーをtar/zipにまとめるために設計されています。私たちはすぐにそれを解凍し、単語を数えます。 (明らかに出力形式を微調整することができ、必要に応じてwc -wの独自のカウント機構に置き換えることができます)。

これはすでにかなり早いです。数年前のラップトップでは、約1/20MBの作業ツリーでレポ。もちろん

、あなたが本当にパフォーマンスを心配している場合、おそらく絶対最速方法は、各コミットのために、各ブロブのためのワードカウントを塊の上にワードカウントを合計すると、保存、ツリーを歩くことであろうようにしますそれらを再考する必要はありません。しかし、これは実装すべきもっと多くの作業の一面です。擬似コードは次のようになります。

word_counts(range) 
    for (commit in `git rev-list <range>`) 
     sum = 0 
     for (blob in second_field_of(`git ls-tree -r commit`)) 
      if (!counts[blob]) 
       counts[blob] = word_count(`git cat-file blob`) 
      total_count += counts[blob] 
     print pretty_format(commit), total_count 

pretty_format(commit) 
    return `git log -n 1 --pretty=... commit` 

これは、再読み込みすべての変更されていないファイルに持つ回避することにより、不要な中間ステップ、さらに最適化しを回避することができます。大したことではない可能性のある小さなリポジトリでは、大きなリポジトリでは膨大な処理が行われます。平均サイズ20KBの平均タッチファイルをコミットする20MBのレポを想像してください。

+0

bashループに感謝します。私はgitが含まれている答えを探していた、あなたは、ジェーディイを渡した! –

関連する問題