힘내 비난 커밋 통계


198

각 커미터에서 시작된 저장소에 현재 얼마나 많은 행 (코드)이 있는지 통계를 제공하기 위해 어떻게 비난 (또는 더 적합한 기능 및 / 또는 쉘 명령과 함께)을 "남용"할 수 있습니까?

출력 예 :

Committer 1: 8046 Lines
Committer 2: 4378 Lines

11
실제로는 내장 명령이 있어야합니다 ... 덜 일반적인 사용 사례에 대한 명령이 있습니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

@CiroSantilli 그러나 git에서 피할 수없는 쉘 스크립트를 추가하는 것은 쉽습니다.
Alex

Git 리포지토리에서 특정 작성자가 변경 한 총 줄 수를 계산하는 방법에 대한 가능한 중복 ? 그것은 쉽게 하나 감소 할 수 있기 때문에 모든 저자를 통해 단지 루프
치로 틸리郝海东冠状病六四事件法轮功

1
이것은 아주 굉장 code.google.com/p/gitinspector 당신이 (이 각 개별 파일을 비난하기 때문에 큰 프로젝트가 느린 ... 적용 할 필요가 없습니다) 학생 팀이 과제를 채점하고, 특히
sehe

답변:


166

최신 정보

git ls-tree -r -z --name-only HEAD -- */*.c | xargs -0 -n1 git blame \
--line-porcelain HEAD |grep  "^author "|sort|uniq -c|sort -nr

도중에 몇 가지 사항을 업데이트했습니다.

편의상이 명령을 자체 명령에 넣을 수도 있습니다.

#!/bin/bash

# save as i.e.: git-authors and set the executable flag
git ls-tree -r -z --name-only HEAD -- $1 | xargs -0 -n1 git blame \
 --line-porcelain HEAD |grep  "^author "|sort|uniq -c|sort -nr

이것을 경로 어딘가에 저장하거나 경로를 수정하고 다음과 같이 사용하십시오

  • git authors '*/*.c' # look for all files recursively ending in .c
  • git authors '*/*.[ch]' # look for all files recursively ending in .c or .h
  • git authors 'Makefile' # just count lines of authors in the Makefile

원래 답변

허용 된 답변이 효과가 있지만 매우 느립니다.

$ git ls-tree --name-only -z -r HEAD|egrep -z -Z -E '\.(cc|h|cpp|hpp|c|txt)$' \
  |xargs -0 -n1 git blame --line-porcelain|grep "^author "|sort|uniq -c|sort -nr

거의 즉각적입니다.

현재 추적 된 파일 목록을 얻으려면

git ls-tree --name-only -r HEAD

이 솔루션은 file파일 형식을 결정하기 위해 호출하지 않고 성능상의 이유로 grep을 사용하여 원하는 확장명을 찾습니다. 모든 파일이 포함되어야한다면, 이것을 라인에서 제거하십시오.

grep -E '\.(cc|h|cpp|hpp|c)$' # for C/C++ files
grep -E '\.py$'               # for Python files

파일에 공백이 포함될 수 있으며 쉘에 좋지 않은 경우 다음을 사용할 수 있습니다.

git ls-tree -z --name-only -r HEAD | egrep -Z -z '\.py'|xargs -0 ... # passes newlines as '\0'

xargs를 사용하여 명령을 호출하고 인수를 분배 할 수있는 파일 목록 (파이프를 통해)을 제공하십시오. 여러 파일을 처리 할 수있는 명령은 -n1. 이 경우 우리는 호출 git blame --line-porcelain하고 모든 호출에 대해 정확히 1 개의 인수를 사용합니다.

xargs -n1 git blame --line-porcelain

그런 다음 "author"발생을 위해 출력을 필터링하여 목록을 정렬하고 중복 행을 계산합니다.

grep "^author "|sort|uniq -c|sort -nr

노트

다른 답변은 실제로 공백 만 포함하는 행을 필터링합니다.

grep -Pzo "author [^\n]*\n([^\n]*\n){10}[\w]*[^\w]"|grep "author "

위의 명령은 공백이 아닌 문자를 하나 이상 포함하는 행 작성자를 인쇄합니다. 또한 \w*[^\w#]공백이 아닌 첫 문자가 아닌 행을 제외시키는 match 를 사용할 수도 있습니다 #(많은 스크립팅 언어의 주석).


2
@ nilbus : 당신은 할 수 없습니다. echo "a\nb\nc"|xargs -n1 cmd다음으로 확장cmd a; cmd b; cmd d
Alex

2
--line-도자기 대신 더 이상 (자식 1.7.5.4) 작동 --porcelain 사용하지 않는 것
isoiphone

4
OSX 사용자는 다음을 시도하십시오 (여전히 이름에 줄 바꿈이있는 파일에서는 작동하지 않습니다) :git ls-tree --name-only -r HEAD | grep -E '\.(cc|h|m|hpp|c)$' | xargs -n1 git blame --line-porcelain | grep "^author "|sort|uniq -c|sort -nr
Wayne

3
현재 경로 아래의 모든 것을 원하는 깊이까지 원하는 경우 "./"를 경로 필터로 사용하십시오 (응답자가 " / .c"를 입력).
벤 Dilts

2
코드는 포맷 할 때 아마 더 나은 코드 소유권을 얻기 위해 "비난 -w"를 사용 stackoverflow.com/questions/4112410/...
sleeplessnerd

124

유용한 git-fame 이라는 보석을 썼습니다 .

설치 및 사용법 :

  1. $ gem install git_fame
  2. $ cd /path/to/gitdir
  3. $ git fame

산출:

Statistics based on master
Active files: 21
Active lines: 967
Total commits: 109

Note: Files matching MIME type image, binary has been ignored

+----------------+-----+---------+-------+---------------------+
| name           | loc | commits | files | distribution (%)    |
+----------------+-----+---------+-------+---------------------+
| Linus Oleander | 914 | 106     | 21    | 94.5 / 97.2 / 100.0 |
| f1yegor        | 47  | 2       | 7     |  4.9 /  1.8 / 33.3  |
| David Selassie | 6   | 1       | 2     |  0.6 /  0.9 /  9.5  |
+----------------+-----+---------+-------+---------------------+

5
+1 마침내 1이 작동하고 합리적인 숫자를 제공하는 것처럼 보이며 나머지 명령 줄은 유틸리티 비 호환성으로 인해 OSX에서 작동하지 않거나 내 저장소에 작은 숫자를 제공합니다. 이것은 OSX와 루비 1.9.3 (brew)에 있습니다
Karthik T

9
바보 같이 굴지 마, @tcaswell. 당신이 무언가를 쓰는 사람이더라도, 유용한 것을 지적하는 것은 스팸이 아닙니다.
Wayne

5
내 자신의 질문에 대답 : git fame --exclude = paths / to / files, paths / to / other / files
Maciej Swic

2
@ 아담 : 여전히 문제가 있습니까? OS X 10.9.5에서 매우 잘 작동합니다.
Sam Dutton

2
이 보석이 수행하는 데 필요한 시간보다 몇 커밋보다 큰 레포는 모두 천문학적입니다
Erik Aigner

48
git ls-tree -r HEAD|sed -re 's/^.{53}//'|while read filename; do file "$filename"; done|grep -E ': .*text'|sed -r -e 's/: .*//'|while read filename; do git blame -w "$filename"; done|sed -r -e 's/.*\((.*)[0-9]{4}-[0-9]{2}-[0-9]{2} .*/\1/' -e 's/ +$//'|sort|uniq -c

단계별 설명 :

버전 관리중인 모든 파일 나열

git ls-tree -r HEAD|sed -re 's/^.{53}//'

텍스트 파일로만 목록 정리

|while read filename; do file "$filename"; done|grep -E ': .*text'|sed -r -e 's/: .*//'

Git은 공백을 무시하고 모든 텍스트 파일을 비난합니다.

|while read filename; do git blame -w "$filename"; done

저자 이름을 뽑아

|sed -r -e 's/.*\((.*)[0-9]{4}-[0-9]{2}-[0-9]{2} .*/\1/' -e 's/ +$//'

저자 목록을 정렬하고 uniq가 연속적으로 반복되는 행 수를 계산하도록합니다.

|sort|uniq -c

출력 예 :

   1334 Maneater
   1924 Another guy
  37195 Brian Ruby
   1482 Anna Lambda

1
내가 다른 sed버전을 가지고있는 것처럼 보며 -r깃발을 이해하지 못하고 정규 표현식에 문제가 있습니다 (여분을 제거 할 때도 불균형 한 parens에 대해 불평합니다 ().
Erik Aigner

7
신경 쓰지 마라 sudo brew install gnu-sed. 매력처럼 작동합니다!
Erik Aigner

5
또는 port install gsedMacPorts 사용자의 경우.
Gavin Brock

나는 sudo brew install gnu-sed(작동했다)했지만 sed가 -r을 인식하지 못하는 오류가 여전히 발생합니다. :(
Adam Tuttle

1
macports를 통해 gsed를 설치 한 후 OSX에서이 명령을 실행하여 sed를 gsed로 교체했습니다.git ls-tree -r HEAD|gsed -re 's/^.{53}//'|while read filename; do file "$filename"; done|grep -E ': .*text'|gsed -r -e 's/: .*//'|while read filename; do git blame -w "$filename"; done|gsed -r -e 's/.*\((.*)[0-9]{4}-[0-9]{2}-[0-9]{2} .*/\1/' -e 's/ +$//'|sort|uniq -c
nerdherd

38

git summarygit-extras 패키지 에서 제공하는 것은 정확히 필요한 것입니다. git-extras-git-summary 에서 문서를 확인하십시오 .

git summary --line

다음과 같은 출력을 제공합니다.

project  : TestProject
lines    : 13397
authors  :
8927 John Doe            66.6%
4447 Jane Smith          33.2%
  23 Not Committed Yet   0.2%

1
멋지지만 경로 필터 또는 적어도 하위 디렉토리 인수를 지원하지 않는 것 같습니다. 더 좋을 것입니다.
spinkus

1
좋고 깨끗한 솔루션. @Alex의 대답은 어떤 이유로 매우 작은 라인 수를 산출했습니다. 이것은 방금 상자 밖으로 작동했습니다. 수백 개의 파일에 걸쳐 ~ 200k 라인에 30 초 정도 걸리는 것.
fgblomqvist

6

Erik의 솔루션은 훌륭했지만, 분음 부호 ( LC_*환경 변수가 표면적으로 올바르게 설정되어 있음에도 불구하고)에 문제가 있었으며 실제로 날짜가있는 코드 줄에서 노이즈가 누출되었습니다. 내 sed-fu는 가난하기 때문에 루비가 들어간이 프랑켄슈타인 스 니펫으로 끝났지 만 200,000 + LOC에서 완벽하게 작동하며 결과를 정렬합니다.

git ls-tree -r HEAD | gsed -re 's/^.{53}//' | \
while read filename; do file "$filename"; done | \
grep -E ': .*text' | gsed -r -e 's/: .*//' | \
while read filename; do git blame "$filename"; done | \
ruby -ne 'puts $1.strip if $_ =~ /^\w{8} \((.*?)\s*\d{4}-\d{2}-\d{2}/' | \
sort | uniq -c | sort -rg

또한 바이너리 brewbrew 설치이기 때문에 시스템 sed를 그대로두기 때문에 gsed대신에 유의하십시오 sed.


4

git shortlog -sn

작성자 당 커밋 목록이 표시됩니다.


17
이렇게하면 줄당이 아니라 작성자 당 커밋 수가 반환됩니다.
v64

프로젝트 / 디렉토리 / 파일의 주요 기고자를 결정하는 데 매우 도움이됩니다
Ares

4

다음은 @Alex의 답변에서 실제로 비난 라인을 집계하는 작업을 수행하는 기본 스 니펫입니다. 파일 세트가 아닌 단일 파일 에서 작동하도록 줄 였습니다.

git blame --line-porcelain path/to/file.txt | grep  "^author " | sort | uniq -c | sort -nr

나는이 답변에 자주 돌아와서 게시물을 다시 읽고 예제를 다시 소화하여 과세 대상 부분을 추출하기 때문에 여기에 게시합니다. 또한 내 유스 케이스에 대해 일반적인 것이 아닙니다. 그 범위는 전체 C 프로젝트입니다.


떠들썩한로를 통해 achived 파일 당 목록 통계에 같은 I for반복자 대신 xargs내가 사용 / 암기, 장점 / 단점에 xargs를 덜 읽고 하드를 찾으로 에 대한 대 xargs를 다른 곳에서 논의되어야한다.

다음은 각 파일의 결과를 개별적으로 표시하는 실용적인 스 니펫입니다.

for file in $(git ls-files); do \
    echo $file; \
    git blame --line-porcelain $file \
        | grep  "^author " | sort | uniq -c | sort -nr; \
    echo; \
done

그리고 bash 쉘 에서이 stright를 실행하는 것이 ctrl + c 안전하다는 것을 테스트했습니다 .bash 스크립트 안에 이것을 배치 해야하는 경우 사용자가 for 루프를 끊을 수 있도록하려면 SIGINT 및 SIGTERM트랩 해야 할 수도 있습니다 .


1
git blame -w -M -C -C --line-porcelain path/to/file.txt | grep -I '^author ' | sort | uniq -ic | sort -nr내가 찾고 있던 통계를 더 정확하게 묘사하는 git blame 여기에 약간의 조정이 있음을 발견했습니다 . 특히, -M 및 -C -C 옵션 (이 두 가지는 C입니다). -M은 파일 내에서의 이동을 감지하고 -C -C는 다른 파일에서 복사 된 행을 감지합니다. doc here 참조 하십시오 . 완전성을 위해 -w는 공백을 무시합니다.
John Lee


1

이 솔루션은 모든 텍스트 파일 (이진 파일, 버전이 지정된 파일 제외)의 비난을 계산합니다.

IFS=$'\n'
for file in $(git ls-files); do
    git blame `git symbolic-ref --short HEAD` --line-porcelain "$file" | \
        grep  "^author " | \
        grep -v "Binary file (standard input) matches" | \
        grep -v "Not Committed Yet" | \
        cut -d " " -f 2-
    done | \
        sort | \
        uniq -c | \
        sort -nr

1

특정 소스 모듈을 검사하려는 경우 repo 소스 구조의 모든 디렉토리에서 작동합니다.

find . -name '*.c' | xargs -n1 git blame --line-porcelain | grep "^author "|sort|uniq -c|sort -nr

0

Powershell에 대한 최고의 답변 을 채택했습니다 .

(git ls-tree -rz --name-only HEAD).Split(0x00) | where {$_ -Match '.*\.py'} |%{git blame -w --line-porcelain HEAD $_} | Select-String -Pattern '^author ' | Group-Object | Select-Object -Property Count, Name | Sort-Object -Property Count -Descending

그것은 당신이 실행 여부에 옵션의 git blame-w 는 공백 변경 내용을 무시하기 때문에 스위치, 나는 그것을했다.

Bash 솔루션이 WSL2 에서 실행되었지만 내 컴퓨터의 성능은 Powershell (동일한 저장소의 경우 ~ 50 대 ~ 65s)을 선호했습니다.


-1

@nilbus와 @Alex의 조합 인 내 스크립트를 만들었습니다.

#!/bin/sh

for f in $(git ls-tree -r  --name-only HEAD --);
do
    j=$(file "$f" | grep -E ': .*text'| sed -r -e 's/: .*//');
    if [ "$f" != "$j" ]; then
        continue;
    fi
    git blame -w --line-porcelain HEAD "$f" | grep  "^author " | sed 's/author //'`enter code here`
done | sort | uniq -c | sort -nr

나를 위해, 당신의 문제 enter code here가 발생했습니다 ....이 제대로 작동합니까?
Menios

-1

MacOS에서 실행되는 단일 소스 파일을 대상으로하는 Bash 기능.

function glac {
    # git_line_author_counts
    git blame -w "$1" |  sed -E "s/.*\((.*) +[0-9]{4}-[0-9]{2}.*/\1/g" | sort | uniq -c | sort -nr
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.