Применить команду ко всем коммитам - PullRequest
3 голосов
/ 04 февраля 2012

В попытке собрать статистику о репозитории Git я ищу способ сделать следующее:

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

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

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

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

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

Ответы [ 2 ]

7 голосов
/ 04 февраля 2012

Чтобы вычислить размер каждого коммита в репо, проверять каждый коммит будет довольно медленно. Во-первых, вы дублируете лот работы, так как вы будете пересчитывать размеры файлов, которые не меняются. Кроме того, вы будете постоянно проверять свою файловую систему. Вот скрипт, который запрашивает git-репо, чтобы получить необходимую информацию. Основное преимущество заключается в том, что вы никогда не смотрите на двоичные объекты, чтобы вычислить их размер, а просто попросите git сообщить вам. Кроме того, вы запрашиваете git для каждого блоба только один раз (через магию Memoize).
Нет сомнений в том, что этот скрипт нуждается в работе (было бы неплохо использовать autodie для обнаружения ошибок git), но он должен дать вам место для начала. (Я изменил это из оригинальной публикации, чтобы включить аргумент, который можно использовать в качестве refspec. Если вызывается без аргумента, это печатает информацию для каждой фиксации в истории. ограничить работу. Например, если у вас есть теги 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="%T@%ci" $commit | sed 1q ));
    chop $date;
    printf "$date: %d\n", compute_tree_size $tree;
}
2 голосов
/ 04 февраля 2012

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

Вот как вы могли бы сделать это с помощью bash:

#! /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")

Предупреждение: это оставит вас в состоянии отсоединенной головы, при самом старом коммите, что нехорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...