2012-02-04 4 views
3

В попытке собрать некоторые статистические данные о репозитории Git, я искал способ сделать следующее:Применить команду для всех фиксаций

  • Для каждого коммита, выполнить команду (напр, du -h).
  • Эта команда должна запускаться из базового каталога хранилища, «как это было похоже» после фиксации.
  • В идеале команда должна иметь доступ к хэшу фиксации и метке времени.

Одно приложение, выраженное в квази-Баш, было бы запустить

echo $HASH $TIME `du -hs --exclude=".git" . | awk '{ print $1; }'` >> ../sizeovertime 

на всех фиксаций, чтобы получить представление о росте хранилища.

(Каким-то образом, он чувствует, как это должно быть возможно использовать git filter-branch --tree-filter для этого, но это выглядит как ужасный хак ко мне.)

ответ

2

Я не понимаю, как вы могли бы сделать это, не проверив при каждой фиксации, так что это займет некоторое время в большом хранилище.

Вот как вы можете это сделать с Баш:

#! /bin/bash 

while read co dt ; do 
    git checkout $co > /dev/null 2>&1 
    size=$(du -hs --exclude=.git|cut -f1) 
    echo $co $size $dt 
done < <(git rev-list --pretty=format:"%H %ci" --all --date-order |grep -v "^commit") 

Внимание: это оставит вас в отдельных состоянии головы, на старейшей фиксации, которая не является хорошим местом, чтобы быть.

+0

Спасибо, я закончил тем, что использовал что-то очень близкое к этому. – Philippe

7

Чтобы вычислить размер каждой фиксации в репо, будет довольно медленно проверять каждую фиксацию. Во-первых, вы дублируете работу , так как вы будете перекомпилировать размеры файлов, которые не меняются. Кроме того, вы будете забивать вашу файловую систему, постоянно проверяя ситуацию. Вот сценарий, который запрашивает git repo, чтобы получить необходимую вам информацию. Основное преимущество заключается в том, что вы никогда не смотрите на какой-либо из блоков, чтобы вычислить их размер, а просто попросите git рассказать вам. Кроме того, вы только запрашиваете git для каждого блоба один раз (через магию Memoize).
Нет сомнений в том, что этот скрипт нуждается в работе (автоматическое распознавание любых сбоев git было бы хорошей идеей), но это должно дать вам место для начала. (Я изменил это из первоначальной публикации, включив аргумент, который можно использовать как refspec.Если вы вызываете без аргумента, это печатает информацию для каждого фиксации в истории. Вы можете передать ref-spec, как rev-list, ограничьте работу. Например, если у вас есть теги v0 и v1, вы можете передать «v0..v1» в качестве первого аргумента.)

#!/usr/bin/env perl 

use warnings; 
use strict; 
use Memoize; 

my $rev_list = $ARGV[ 0 ] || "--all"; 

# Query git for the size of a blob. This is memoized, so we only 
# ask for any blob once. 
sub get_blob_size($) { 
    my $hash = shift; 
    my $size = qx(git cat-file -s $hash); 
    return int($size); 
} 
memoize('get_blob_size'); 

# Recursively compute the size of a tree. Note that git cat-file -s 
# does not give the cumulative size of all the blobs in a tree. 
sub compute_tree_size($); 
sub compute_tree_size($) { 
    my $sha = shift; 
    my $size; 
    open my $objects, '-|', "git cat-file -p $sha"; 
    while(<$objects>) { 
     my ($mode, $type, $hash, $name) = split; 
     if($type eq 'blob') { 
      $size += get_blob_size($hash); 
     } elsif($type eq 'tree') { 
      $size += compute_tree_size($hash); 
     } 
    } 
    return $size; 
} 
memoize('compute_tree_size'); 

# Generate a list of all commits 
open my $objects, '-|', "git rev-list $rev_list | 
    git cat-file --batch-check"; 

# Traverse the commit list and report on the size of each. 
while(<$objects>) { 
    my($commit, $type, $size) = split; 
    my($tree, $date) = split('@', 
     qx(git show --format="%[email protected]%ci" $commit | sed 1q)); 
    chop $date; 
    printf "$date: %d\n", compute_tree_size $tree; 
} 
+0

Это, кажется, элегантное и умное решение для вычислительных размеров. Я просто приводил это в качестве примера; в моем случае задача была более сложной (создание PDF и преобразование его в изображение). Вот почему я принимаю другой, более общий ответ. – Philippe

+1

@philippe, вы можете использовать это решение в совершенно общем виде. Если вам нужен доступ к данным в блобе, вы можете получить его с git cat-file -p. Просто замените get_blob_size на get_blob и работайте с данными в блобе. Нет необходимости делать чек. –

Смежные вопросы