Git Suçlama İstatistikleri


199

Şu anda her komütatörden gelen depoda ne kadar satır (kod) bulunduğuna dair bir istatistik vermek için suçu nasıl "kötüye kullanabilir" (veya bazı daha uygun işlevler ve / veya kabuk komutlarıyla birlikte)?

Örnek Çıktı:

Committer 1: 8046 Lines
Committer 2: 4378 Lines

11
Bunun için gerçekten yerleşik bir komut olmalı ... çok daha az yaygın kullanım durumları için komutlar var.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

@CiroSantilli ama git'ten çağrılamaz bir kabuk betiği eklemek çok kolay.
Alex

olası yinelenen Nasıl Git depo belirli bir yazar tarafından değiştirilen toplam satırları saymak için? çünkü buna kolayca indirgenebilir: sadece tüm yazarların üzerine
gelin

1
Bu oldukça harika bir kod.google.com/p/gitinspector özellikle öğrenci ekipleri tarafından ödevleri derecelendiriyorsanız (büyük projelerin uygulanması gerekmez ... yavaştır, çünkü her dosyayı tek tek suçlar)
Ocak'ta

Yanıtlar:


166

Güncelleme

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

Yolda bazı şeyleri güncelledim.

Kolaylık sağlamak için bunu kendi komutuna da koyabilirsiniz:

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

bunu yolunuzda bir yerde saklayın veya yolunuzu değiştirin ve

  • 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

Orijinal Yanıt

Kabul edilen cevap işi yaparken yavaştır.

$ 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

neredeyse anlık.

Şu anda izlenen dosyaların bir listesini almak için

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

Bu çözüm file, dosya türünü belirlemek için çağrı yapılmasını önler ve performans nedenleriyle istenen uzantıyla eşleştirmek için grep kullanır. Tüm dosyaların dahil edilmesi gerekiyorsa, bunu satırdan kaldırmanız yeterlidir.

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

dosyalar kabuklar için kötü olan boşluklar içeriyorsa kullanabilirsiniz:

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

Bir komut çağırmak ve bağımsız değişkenleri dağıtmak için xargs kullanarak bir dosya listesi (kanal aracılığıyla) verin. Birden fazla dosyanın işlenmesine izin veren komutlar -n1. Bu durumda çağırırız git blame --line-porcelainve her çağrı için tam olarak 1 argüman kullanırız.

xargs -n1 git blame --line-porcelain

Daha sonra çıktıyı "yazar" oluşumuna göre filtreleyip listeyi sıralıyoruz ve yinelenen satırları sayıyoruz

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

Not

Diğer yanıtlar aslında yalnızca boşluk içeren satırları filtreler.

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

Yukarıdaki komut, en az bir boşluk olmayan karakter içeren satırların yazarlarını yazdıracaktır. Ayrıca \w*[^\w#], boşluk olmayan ilk karakterin a olmayan satırları da hariç tutacak eşleşmeyi kullanabilirsiniz #(birçok komut dosyası dilinde yorum yapın).


2
@ nilbus: yapamazsın. echo "a\nb\nc"|xargs -n1 cmdgenişletilecekcmd a; cmd b; cmd d
Alex

2
--line-porcelain artık işe yaramıyor (git 1.7.5.4) bunun yerine --porcelain
isoiphone

4
OSX kullanıcıları, aşağıdakileri deneyin (adlarında yeni satırları olan dosyalar üzerinde hala çalışmıyor):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
Sadece mevcut yolun altındaki her şeyi istiyorsanız, herhangi bir derinliğe, yol filtresi olarak "./" kullanın (yanıtlayıcının " / .c" koyduğu yer ).
Ben Dilts

2
Belki kod sadece yeniden biçimlendirildiğinde daha iyi kod sahibi olmak için "suçlama -w" kullanın stackoverflow.com/questions/4112410/…
sleeplessnerd

124

Yararlı olabilecek git-fame adlı bir mücevher yazdım .

Kurulum ve kullanım:

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

Çıktı:

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 sonunda 1 çalışıyor ve mantıklı sayılar veriyor gibi görünüyor, komut satırı geri kalanları ya araçlar uyumsuzluğu nedeniyle OSX üzerinde çalışmıyor ya da repoma ufacık sayılar veriyor. Bu OSX ve yakut 1.9.3 (demlemek)
Karthik T

9
Aptal olma, @ tcaswell. Bir şeyi yazacak olsanız bile, yararlı bir şeye işaret etmek spam değildir.
Wayne

5
Kendi sorumu cevaplıyorum: git fame --exclude = yollar / dosya / yollar, yollar / dosya / dosyalar / dosyalar
Maciej Swic

2
@Adam: Hala bununla ilgili sorun mu yaşıyorsunuz? OS X 10.9.5'te benim için çok iyi çalışıyor.
Sam Dutton

2
Birkaç taneden daha büyük olan herhangi bir repo için bu gemin yapması gereken zamanı astronomik yapıyor
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

Adım adım açıklama:

Sürüm denetimi altındaki tüm dosyaları listele

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

Listeyi yalnızca metin dosyalarına indir

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

Git tüm metin dosyalarını suçluyor, boşluk değişikliklerini yok sayarak

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

Yazar adlarını çıkarın

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

Yazarların listesini sıralayın ve art arda yinelenen satırların sayısının benzersiz olarak sayılmasını sağlayın

|sort|uniq -c

Örnek çıktı:

   1334 Maneater
   1924 Another guy
  37195 Brian Ruby
   1482 Anna Lambda

1
Görünüşe göre farklı bir sedversiyonum var, benimki -rbayrağı anlamıyor ve regex ile ilgili sorunları var (fazlalığı kaldırdığımda bile dengesiz parenslerden şikayet ediyor ().
Erik Aigner

7
Boşver, sudo brew install gnu-sedçözdü. Tıkır tıkır çalışıyor!
Erik Aigner

5
Veya port install gsedMacPorts kullanıcıları için.
Gavin Brock

sudo brew install gnu-sed(Hangi çalıştı) yaptım ama hala sed -r tanımıyor hataları alıyorum. :(
Adam Tuttle

1
OSX'de macorts üzerinden gsed yükledikten sonra çalışması için bu komutu çalıştırdım (sed gsed ile değiştirildi):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 paketi tarafından sağlanan tam olarak ihtiyacınız olan şeydir. Git-Extras'taki belgelere göz atın - Git-Summary :

git summary --line

Şuna benzeyen çıktılar verir:

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

1
Güzel, ancak bir yol filtresini veya en azından bir alt dizin argümanını desteklemiyor gibi görünüyor. Güzel olurdu.
spinkus

1
Güzel ve temiz bir çözüm. @ Alex'in yanıtı bir sebepten dolayı çok küçük satır sayıları verdi. Bu sadece kutudan çıktı. Birkaç yüz dosyaya yayılmış ~ 200 bin satır için 30 saniye gibi bir şey aldı.
fgblomqvist

6

Erik'in çözümü harikaydı, ancak diyakritiklerle ( LC_*ortam değişkenlerimin görünüşte doğru bir şekilde ayarlanmasına rağmen ) ve içinde tarih olan kod satırlarından sızan gürültü ile ilgili bazı problemlerim vardı. Benim sed-fu fakir, bu yüzden içinde yakut ile bu frankenstein snippet ile sona erdi, ama benim için 200.000+ LOC kusursuz çalışır ve sonuçları sıralar:

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

Ayrıca gsedbunun yerine sedikili homebrew kurulumları, sistem sed bozulmadan bırakarak unutmayın .


4

git shortlog -sn

Bu, yazar başına taahhütlerin bir listesini gösterecektir.


17
Bu satır başına değil yazar başına taahhüt sayısını döndürür.
v64

Bir projeye / dizine / dosyaya ana katkıda bulunanları belirlemede çok yardımcı
Ares

4

İşte @Alex'in cevabından, suçlu hatlarını toplama işlemini yapan birincil snippet. Bir dosya kümesi yerine tek bir dosya üzerinde çalışmak için kestim .

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

Bunu buraya gönderiyorum çünkü bu cevaba sık sık geri dönüyorum ve gönderiyi tekrar okudum ve vergilendirdiğim değeri çıkarmak için örnekleri tekrar sindiriyorum. Benim kullanım durumum için yeterince genel değil; kapsamı bütün bir C projesi içindir.


Ben xargs daha az okunabilir ve kullanımı / ezberlemek zor bulmak gibi bir bash foryineleyici ile elde dosya başına istatistiklerini listeleme gibi xargs, xargs vs için avantaj / dezavantajları başka bir yerde tartışılmalıdır.

Her dosya için sonuçları ayrı ayrı gösterecek pratik bir snippet:

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

Ve test ettim, bu stresi bir bash kabuğunda çalıştırmak ctrl + c güvenli, eğer bunu bir bash betiğinin içine koymanız gerekiyorsa , kullanıcının döngü için kırılmasını istiyorsanız, SIGINT ve SIGTERM üzerinde tuzak yapmanız gerekebilir .


1
git blame -w -M -C -C --line-porcelain path/to/file.txt | grep -I '^author ' | sort | uniq -ic | sort -nrgit blame Burada aradığım istatistikleri daha doğru bir şekilde tasvir eden hafif bir tweak buldum. Özellikle, -M ve -C -C seçeneği (bunlar amaç için iki C'dir). -M dosya içindeki hareketleri algılar ve -C -C diğer dosyalardan kopyalanan satırları algılar. Buradaki dokümana bakınız . Tamlık uğruna, -w boşlukları yok sayar.
John Lee


1

(İkili dosyalar, hatta sürümlü olanlar hariç) tüm metin dosyalarında suçlu satırları sayar bu çözüm var:

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

Belirli bir kaynak modülünü denetlemek istediğinizde, repo'nun kaynak yapısının herhangi bir dizininde çalışır.

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

0

Powershell'e en iyi cevabı verdim :

(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

Bu, çalıştırmak konusunda isteğe bağlıdır git blameile -wbu boşluk değişiklikleri göz ardı çünkü anahtarı, bunu ekledi.

Bash çözümü WSL2 altında çalışmasına rağmen, makinemdeki performans Powershell (~ 50s vs ~ 65s) idi.


-1

@Nilbus ve @Alex'in bir birleşimi olan kendi senaryomu hazırladım

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

Benim için işin enter code heresorunlara neden oluyordu ... bu doğru çalışıyor mu?
Menios

-1

MacOS'ta çalışan tek bir kaynak dosyasını hedefleyen Bash işlevi.

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
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.