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.