Как подсчитать общее количество строк, измененных конкретным автором в репозитории Git?
есть ли команда, которую я могу вызвать, которая будет считать строки, измененные конкретным автором в репозитории Git? Я знаю, что должны быть способы подсчета количества коммитов, поскольку Github делает это для своего графика воздействия.
21 ответов:
вывод следующей команды должен быть достаточно легко отправить в скрипт, чтобы сложить итоги:
git log --author="<authorname>" --oneline --shortstatэто дает статистику для всех коммитов на текущей голове. Если вы хотите добавить статистику в других ветвях, вам придется предоставить их в качестве аргументов для
git log.для перехода к сценарию удаление даже формата "oneline" может быть сделано с пустым форматом журнала, и, как прокомментировал Якуб Нарембский,
--numstatэто еще одна альтернатива. Он генерирует статистика по файлам, а не по строкам, но ее еще проще анализировать.git log --author="<authorname>" --pretty=tformat: --numstat
это дает некоторую статистику об авторе, изменить по мере необходимости.
С Помощью Gawk:
git log --author="_Your_Name_Here_" --pretty=tformat: --numstat \ | gawk '{ add += ; subs += ; loc += - } END { printf "added lines: %s removed lines: %s total lines: %s\n", add, subs, loc }' -использование Awk на Mac OSX:
git log --author="_Your_Name_Here_" --pretty=tformat: --numstat | awk '{ add += ; subs += ; loc += - } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -EDIT (2017)
на github есть новый пакет, который выглядит гладким и использует bash в качестве зависимостей (протестирован на linux). Это больше подходит для прямого использования, а не Скрипты.
Это ЖКТ-быстрая статистика (ссылка на GitHub).
скопировать
git-quick-statsв папку и добавить путь к папке.mkdir ~/source cd ~/source git clone [email protected]:arzzen/git-quick-stats.git mkdir ~/bin ln -s ~/source/git-quick-stats/git-quick-stats ~/bin/git-quick-stats chmod +x ~/bin/git-quick-stats export PATH=${PATH}:~/binиспользование:
git-quick-stats
в случае, если кто-то хочет посмотреть статистика каждый пользователь в своей кодовой базе, несколько моих коллег недавно придумали этот ужасный однострочный:
git log --shortstat --pretty="%cE" | sed 's/\(.*\)@.*//' | grep -v "^$" | awk 'BEGIN { line=""; } !/^ / { if (line=="" || !match(line, )) {line = "," line }} /^ / { print line " # " ; line=""}' | sort | sed -E 's/# //;s/ files? changed,//;s/([0-9]+) ([0-9]+ deletion)/ 0 insertions\(+\), /;s/\(\+\)$/\(\+\), 0 deletions\(-\)/;s/insertions?\(\+\), //;s/ deletions?\(-\)//' | awk 'BEGIN {name=""; files=0; insertions=0; deletions=0;} {if ( != name && name != "") { print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net"; files=0; insertions=0; deletions=0; name=; } name=; files+=; insertions+=; deletions+=} END {print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net";}'(требуется несколько минут, чтобы пробить наше РЕПО, которое имеет около 10-15k коммитов.)
Git famehttps://github.com/oleander/git-fame-rb
это хороший инструмент, чтобы получить количество для всех авторов сразу, в том числе фиксации и измененных файлов count:
sudo apt-get install ruby-dev sudo gem install git_fame cd /path/to/gitdir && git fameсуществует также версия Python в https://github.com/casperdcl/git-fame (упоминается @fracz):
sudo apt-get install python-pip python-dev build-essential pip install --user git-fame cd /path/to/gitdir && git fameпример вывода:
Total number of files: 2,053 Total number of lines: 63,132 Total number of commits: 4,330 +------------------------+--------+---------+-------+--------------------+ | name | loc | commits | files | percent | +------------------------+--------+---------+-------+--------------------+ | Johan Sørensen | 22,272 | 1,814 | 414 | 35.3 / 41.9 / 20.2 | | Marius Mathiesen | 10,387 | 502 | 229 | 16.5 / 11.6 / 11.2 | | Jesper Josefsson | 9,689 | 519 | 191 | 15.3 / 12.0 / 9.3 | | Ole Martin Kristiansen | 6,632 | 24 | 60 | 10.5 / 0.6 / 2.9 | | Linus Oleander | 5,769 | 705 | 277 | 9.1 / 16.3 / 13.5 | | Fabio Akita | 2,122 | 24 | 60 | 3.4 / 0.6 / 2.9 | | August Lilleaas | 1,572 | 123 | 63 | 2.5 / 2.8 / 3.1 | | David A. Cuadrado | 731 | 111 | 35 | 1.2 / 2.6 / 1.7 | | Jonas Ängeslevä | 705 | 148 | 51 | 1.1 / 3.4 / 2.5 | | Diego Algorta | 650 | 6 | 5 | 1.0 / 0.1 / 0.2 | | Arash Rouhani | 629 | 95 | 31 | 1.0 / 2.2 / 1.5 | | Sofia Larsson | 595 | 70 | 77 | 0.9 / 1.6 / 3.8 | | Tor Arne Vestbø | 527 | 51 | 97 | 0.8 / 1.2 / 4.7 | | spontus | 339 | 18 | 42 | 0.5 / 0.4 / 2.0 | | Pontus | 225 | 49 | 34 | 0.4 / 1.1 / 1.7 | +------------------------+--------+---------+-------+--------------------+но имейте в виду: как упоминал Джаред в комментарии, делать это на очень большой хранилище займет несколько часов. Не уверен, что это может быть улучшено, хотя, учитывая, что он должен обрабатывать так много данных Git.
Я нашел следующее полезным, чтобы увидеть, у кого было больше строк, которые в настоящее время находятся в базе кода:
git ls-files -z | xargs -0n1 git blame -w | ruby -n -e '$_ =~ /^.*\((.*?)\s[\d]{4}/; puts .strip' | sort -f | uniq -c | sort -nдругие ответы в основном сосредоточены на линиях, измененных в коммитах, но если коммиты не сохраняются и перезаписываются, они могут просто быть отточены. Приведенное выше заклинание также позволяет вам сортировать всех коммиттеров по строкам, а не только по одному за раз. Вы можете добавить некоторые параметры в git blame (- C-M), чтобы получить некоторые лучшие числа, которые принимают движение файла и строку перемещение между файлами учитывается, но команда может выполняться намного дольше, если вы это сделаете.
кроме того, если вы ищете строки, измененные во всех коммитах для всех коммиттеров, следующий небольшой скрипт полезен:
подсчитать количество commits данным автором (или всеми авторами) на данной ветке вы можете использовать git-shortlog; см. Особенно его
--numberedи--summaryпараметры, например, при запуске в репозитории git:$ git shortlog v1.6.4 --numbered --summary 6904 Junio C Hamano 1320 Shawn O. Pearce 1065 Linus Torvalds 692 Johannes Schindelin 443 Eric Wong
после Алекс и Gerty3000ответ, я попытался сократить один лайнер:
в основном, используя git log numstat и не отслеживание количества файлы изменен.
Git версия 2.1.0 на Mac OSX:
git log --format='%aN' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --pretty=tformat: --numstat | awk '{ add += ; subs += ; loc += - } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -; doneпример:
Jared Burrows added lines: 6826, removed lines: 2825, total lines: 4001
на ответ С AaronM использование оболочки one-liner хорошо, но на самом деле есть еще одна ошибка, когда пробелы будут повреждать имена пользователей, если между именем пользователя и датой есть разные пробелы. Поврежденные имена пользователей будут давать несколько строк для подсчета пользователей, и вы должны суммировать их самостоятельно.
Это небольшое изменение исправило проблему для меня:
git ls-files -z | xargs -0n1 git blame -w | perl -n -e '/^.*?\((.*?)\s+[\d]{4}/; print ,"\n"' | sort -f | uniq -c | sort -nобратите внимание на + после \s, который будет потреблять все пробелы от имени до даты.
на самом деле добавление этого ответа столько же для моей собственной памяти, сколько для помощи кому-либо еще, так как это, по крайней мере, второй раз, когда я google тему :)
@mmrobins @AaronM @ErikZ @JamesMishra предоставил варианты, которые имеют общую проблему: они просят git создать смесь информации, не предназначенную для потребления скрипта, включая содержимое строки из репозитория в той же строке, а затем сопоставить беспорядок с регулярным выражением.
это проблема, когда некоторые строки не являются допустимым текстом UTF-8, а также когда некоторые строки совпадают с регулярным выражением (это произошло здесь).
вот модифицированная строка, которая не имеет этих проблем. Он запрашивает git для вывода данных чисто на отдельных строках, что позволяет легко фильтровать то, что мы хотим надежно:
git ls-files -z | xargs -0n1 git blame -w --line-porcelain | grep -a "^author " | sort -f | uniq -c | sort -nвы можете grep для других строк, таких как author-mail, committer и т. д.
может, сначала сделать
export LC_ALL=C(еслиbash) для принудительной обработки на уровне байтов (это также значительно ускоряет grep из локалей на основе UTF-8).
вот краткий сценарий, который создает статистику для всех авторов. Это намного быстрее, чем решение Дэна выше вhttps://stackoverflow.com/a/20414465/1102119 (Мой имеет временную сложность O(N) вместо O (NM), где N-количество коммитов, а M-количество авторов).
git log --no-merges --pretty=format:%an --numstat | awk '/./ && !author { author = ; next } author { ins[author] += ; del[author] += } /^$/ { author = ""; next } END { for (a in ins) { printf "%10d %10d %10d %s\n", ins[a] - del[a], ins[a], del[a], a } }' | sort -rn
решение было дано с ruby в середине, perl был немного более доступен по умолчанию вот альтернатива с использованием perl для текущих строк автором.
git ls-files -z | xargs -0n1 git blame -w | perl -n -e '/^.*\((.*?)\s*[\d]{4}/; print ,"\n"' | sort -f | uniq -c | sort -n
кроме ответ Чарльза Бейли, вы можете добавить
-Cпараметр для команд. В противном случае переименования файлов считаются большим количеством добавлений и удалений (столько, сколько в файле есть строк), даже если содержимое файла не было изменено.чтобы проиллюстрировать, вот a commit С большим количеством файлов перемещается из одного из моих проектов, при использовании :
9052459 Reorganized project structure 43 files changed, 1049 insertions(+), 1000 deletions(-)и здесь же совершают с помощью
git log --oneline --shortstat -Cкоманда, которая обнаруживает копии файлов и переименовывает:9052459 Reorganized project structure 27 files changed, 134 insertions(+), 85 deletions(-)
вот быстрый скрипт ruby, который загоняет влияние на пользователя против данного запроса журнала.
например,рубиниус:
Brian Ford: 4410668 Evan Phoenix: 1906343 Ryan Davis: 855674 Shane Becker: 242904 Alexander Kellett: 167600 Eric Hodel: 132986 Dirkjan Bussink: 113756 ...сценарий:
#!/usr/bin/env ruby impact = Hash.new(0) IO.popen("git log --pretty=format:\"%an\" --shortstat #{ARGV.join(' ')}") do |f| prev_line = '' while line = f.gets changes = /(\d+) insertions.*(\d+) deletions/.match(line) if changes impact[prev_line] += changes[1].to_i + changes[2].to_i end prev_line = line # Names are on a line of their own, just before the stats end end impact.sort_by { |a,i| -i }.each do |author, impact| puts "#{author.strip}: #{impact}" end
Я предоставил модификацию короткого ответа выше, но этого было недостаточно для моих нужд. Мне нужно было иметь возможность классифицировать как зафиксированные строки, так и строки в окончательном коде. Я также хотел разбить по файлам. Этот код не возвращается, он будет возвращать только результаты для одного каталога, но это хорошее начало, если кто-то хотел идти дальше. Скопируйте и вставьте в файл и сделайте исполняемый файл или запустите его с помощью Perl.
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $dir = shift; die "Please provide a directory name to check\n" unless $dir; chdir $dir or die "Failed to enter the specified directory '$dir': $!\n"; if ( ! open(GIT_LS,'-|','git ls-files') ) { die "Failed to process 'git ls-files': $!\n"; } my %stats; while (my $file = <GIT_LS>) { chomp $file; if ( ! open(GIT_LOG,'-|',"git log --numstat $file") ) { die "Failed to process 'git log --numstat $file': $!\n"; } my $author; while (my $log_line = <GIT_LOG>) { if ( $log_line =~ m{^Author:\s*([^<]*?)\s*<([^>]*)>} ) { $author = lc(); } elsif ( $log_line =~ m{^(\d+)\s+(\d+)\s+(.*)} ) { my $added = ; my $removed = ; my $file = ; $stats{total}{by_author}{$author}{added} += $added; $stats{total}{by_author}{$author}{removed} += $removed; $stats{total}{by_author}{total}{added} += $added; $stats{total}{by_author}{total}{removed} += $removed; $stats{total}{by_file}{$file}{$author}{added} += $added; $stats{total}{by_file}{$file}{$author}{removed} += $removed; $stats{total}{by_file}{$file}{total}{added} += $added; $stats{total}{by_file}{$file}{total}{removed} += $removed; } } close GIT_LOG; if ( ! open(GIT_BLAME,'-|',"git blame -w $file") ) { die "Failed to process 'git blame -w $file': $!\n"; } while (my $log_line = <GIT_BLAME>) { if ( $log_line =~ m{\((.*?)\s+\d{4}} ) { my $author = ; $stats{final}{by_author}{$author} ++; $stats{final}{by_file}{$file}{$author}++; $stats{final}{by_author}{total} ++; $stats{final}{by_file}{$file}{total} ++; $stats{final}{by_file}{$file}{total} ++; } } close GIT_BLAME; } close GIT_LS; print "Total lines committed by author by file\n"; printf "%25s %25s %8s %8s %9s\n",'file','author','added','removed','pct add'; foreach my $file (sort keys %{$stats{total}{by_file}}) { printf "%25s %4.0f%%\n",$file ,100*$stats{total}{by_file}{$file}{total}{added}/$stats{total}{by_author}{total}{added}; foreach my $author (sort keys %{$stats{total}{by_file}{$file}}) { next if $author eq 'total'; if ( $stats{total}{by_file}{$file}{total}{added} ) { printf "%25s %25s %8d %8d %8.0f%%\n",'', $author,@{$stats{total}{by_file}{$file}{$author}}{qw{added removed}} ,100*$stats{total}{by_file}{$file}{$author}{added}/$stats{total}{by_file}{$file}{total}{added}; } else { printf "%25s %25s %8d %8d\n",'', $author,@{$stats{total}{by_file}{$file}{$author}}{qw{added removed}} ; } } } print "\n"; print "Total lines in the final project by author by file\n"; printf "%25s %25s %8s %9s %9s\n",'file','author','final','percent', '% of all'; foreach my $file (sort keys %{$stats{final}{by_file}}) { printf "%25s %4.0f%%\n",$file ,100*$stats{final}{by_file}{$file}{total}/$stats{final}{by_author}{total}; foreach my $author (sort keys %{$stats{final}{by_file}{$file}}) { next if $author eq 'total'; printf "%25s %25s %8d %8.0f%% %8.0f%%\n",'', $author,$stats{final}{by_file}{$file}{$author} ,100*$stats{final}{by_file}{$file}{$author}/$stats{final}{by_file}{$file}{total} ,100*$stats{final}{by_file}{$file}{$author}/$stats{final}{by_author}{total} ; } } print "\n"; print "Total lines committed by author\n"; printf "%25s %8s %8s %9s\n",'author','added','removed','pct add'; foreach my $author (sort keys %{$stats{total}{by_author}}) { next if $author eq 'total'; printf "%25s %8d %8d %8.0f%%\n",$author,@{$stats{total}{by_author}{$author}}{qw{added removed}} ,100*$stats{total}{by_author}{$author}{added}/$stats{total}{by_author}{total}{added}; }; print "\n"; print "Total lines in the final project by author\n"; printf "%25s %8s %9s\n",'author','final','percent'; foreach my $author (sort keys %{$stats{final}{by_author}}) { printf "%25s %8d %8.0f%%\n",$author,$stats{final}{by_author}{$author} ,100*$stats{final}{by_author}{$author}/$stats{final}{by_author}{total}; }
Это лучший способ, и это также дает вам четкое представление об общем количестве коммитов всех пользователей
git shortlog -s -n
вы можете использовать whodid (https://www.npmjs.com/package/whodid)
$ npm install whodid -g $ cd your-project-dirи
$ whodid author --include-merge=false --path=./ --valid-threshold=1000 --since=1.weekили
$ whodidтогда вы можете увидеть результат, как это
Contribution state ===================================================== score | author ----------------------------------------------------- 3059 | someguy <[email protected]> 585 | somelady <[email protected]> 212 | niceguy <[email protected]> 173 | coolguy <[email protected]> =====================================================
этот скрипт здесь будет делать. Положите его в authorship.sh, chmod +x это, и вы все готовы.
#!/bin/sh declare -A map while read line; do if grep "^[a-zA-Z]" <<< "$line" > /dev/null; then current="$line" if [ -z "${map[$current]}" ]; then map[$current]=0 fi elif grep "^[0-9]" <<<"$line" >/dev/null; then for i in $(cut -f 1,2 <<< "$line"); do map[$current]=$((map[$current] + $i)) done fi done <<< "$(git log --numstat --pretty="%aN")" for i in "${!map[@]}"; do echo -e "$i:${map[$i]}" done | sort -nr -t ":" -k 2 | column -t -s ":"
сохраните ваши журналы в файл с помощью:
git log --author="<authorname>" --oneline --shortstat > logs.txtдля любителей питона:
with open(r".\logs.txt", "r", encoding="utf8") as f: files = insertions = deletions = 0 for line in f: if ' changed' in line: line = line.strip() spl = line.split(', ') if len(spl) > 0: files += int(spl[0].split(' ')[0]) if len(spl) > 1: insertions += int(spl[1].split(' ')[0]) if len(spl) > 2: deletions += int(spl[2].split(' ')[0]) print(str(files).ljust(10) + ' files changed') print(str(insertions).ljust(10) + ' insertions') print(str(deletions).ljust(10) + ' deletions')ваши выходы будут так:
225 files changed 6751 insertions 1379 deletions
вы хотите Git blame.
есть опция -- show-stats для печати некоторых, ну, статистики.
вопрос, заданный для получения информации о конкретные автор, но многие из ответов были решениями, которые возвращали ранжированные списки авторов, основанные на их измененных строках кода.
Это было то, что я искал, но существующие решения были не совсем идеальны. В интересах людей, которые могут найти этот вопрос через Google, я сделал некоторые улучшения в них и превратил их в сценарий оболочки, который я показываю ниже. Аннотированный (который я продолжу поддерживать) можно найдено на моем Github.
здесь нет зависимости от Perl или Ruby. Кроме того, при подсчете изменений строк учитываются пробелы, переименования и перемещения строк. Просто поместите это в файл и передать свой репозиторий Git в качестве первого параметра.
#!/bin/bash git --git-dir="/.git" log > /dev/null 2> /dev/null if [ $? -eq 128 ] then echo "Not a git repository!" exit 128 else echo -e "Lines | Name\nChanged|" git --work-tree="" --git-dir="/.git" ls-files -z |\ xargs -0n1 git --work-tree="" --git-dir="/.git" blame -C -M -w |\ cut -d'(' -f2 |\ cut -d2 -f1 |\ sed -e "s/ \{1,\}$//" |\ sort |\ uniq -c |\ sort -nr fi
лучший инструмент до сих пор я identfied является gitinspector. Он дает установленный отчет в потребителя, в неделю ЕТК Вы можете установить, как показано ниже с npm
npm install-g gitinspector
ссылки, чтобы получить больше подробности
https://www.npmjs.com/package/gitinspector
https://github.com/ejwa/gitinspector/wiki/Documentation
https://github.com/ejwa/gitinspector
пример команды
gitinspector -lmrTw gitinspector --since=1-1-2017 etc

Comments