Если вы хотели что-то более простое в реализации и не возражаете быть немного неоптимальным и глупым, вы можете сделать это:
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
, если хотите.)
Это уже довольно быстро - на многолетнем ноутбуке на коммит в репо с рабочим деревом 20 МБ уходит около четверти секунды.
Конечно, если вы действительно заботитесь о производительности, то, вероятно, абсолютный самый быстрый метод будет заключаться в том, чтобы при каждом коммите проходить по дереву, суммировать количество слов по каплям и хранить количество слов для каждого капли. так что вам не нужно пересчитывать их. Это чертовски много работы для реализации, хотя. Псевдокод может выглядеть так:
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`
Это позволяет избежать ненужных промежуточных шагов и дополнительно оптимизировать, избегая необходимости повторного чтения любых неизмененных файлов. В крошечных репозиториях это может быть не так уж важно, но в больших репозиториях это очень сложно - представьте себе репо объемом 20 МБ, в котором фиксируются в среднем сенсорные файлы общим размером 20 КБ.