ฉันจะ "ตำหนิ" ตำหนิ (หรือฟังก์ชันที่เหมาะสมยิ่งขึ้นและ / หรือใช้ร่วมกับคำสั่งเชลล์) เพื่อให้สถิติเกี่ยวกับจำนวนบรรทัด (รหัส) ในพื้นที่เก็บข้อมูลที่มาจากผู้ส่งแต่ละคนได้อย่างไร
ตัวอย่างผลลัพธ์:
Committer 1: 8046 Lines
Committer 2: 4378 Lines
ฉันจะ "ตำหนิ" ตำหนิ (หรือฟังก์ชันที่เหมาะสมยิ่งขึ้นและ / หรือใช้ร่วมกับคำสั่งเชลล์) เพื่อให้สถิติเกี่ยวกับจำนวนบรรทัด (รหัส) ในพื้นที่เก็บข้อมูลที่มาจากผู้ส่งแต่ละคนได้อย่างไร
ตัวอย่างผลลัพธ์:
Committer 1: 8046 Lines
Committer 2: 4378 Lines
คำตอบ:
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 .cgit authors '*/*.[ch]' # look for all files recursively ending in .c or .hgit 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
จากนั้นเรากรองผลลัพธ์สำหรับการเกิดขึ้นของ "ผู้เขียน" เรียงลำดับรายการและนับบรรทัดที่ซ้ำกันโดย:
grep "^author "|sort|uniq -c|sort -nr
คำตอบอื่น ๆ จะกรองบรรทัดที่มีช่องว่างเท่านั้น
grep -Pzo "author [^\n]*\n([^\n]*\n){10}[\w]*[^\w]"|grep "author "
คำสั่งด้านบนจะพิมพ์ผู้แต่งบรรทัดที่มีอักขระที่ไม่ใช่ช่องว่างอย่างน้อยหนึ่งตัว นอกจากนี้คุณยังสามารถใช้การจับคู่\w*[^\w#]ซึ่งจะยกเว้นบรรทัดที่อักขระที่ไม่ใช่ช่องว่างตัวแรกไม่ใช่#(แสดงความคิดเห็นในหลายภาษาสคริปต์)
echo "a\nb\nc"|xargs -n1 cmdจะขยายเป็นcmd a; cmd b; cmd d
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
ฉันเขียนพลอยชื่อgit-fameซึ่งอาจมีประโยชน์
การติดตั้งและการใช้งาน:
$ gem install git_fame $ cd /path/to/gitdir$ 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 |
+----------------+-----+---------+-------+---------------------+
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
sedรุ่นที่แตกต่างกันฉันไม่เข้าใจการ-rตั้งค่าสถานะและมีปัญหากับ regex (บ่นเกี่ยวกับ parens ที่ไม่สมดุลแม้ว่าฉันจะเอาส่วนเกินออก()
sudo brew install gnu-sedแก้ไขมัน ทำงานเหมือนจับใจ!
port install gsedสำหรับผู้ใช้ MacPort
sudo brew install gnu-sed(ซึ่งใช้งานได้) แต่ฉันยังคงได้รับข้อผิดพลาดที่ไม่รู้จัก -r :(
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
git summaryให้โดยแพ็คเกจgit-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%
วิธีแก้ปัญหาของ Erik นั้นยอดเยี่ยม แต่ฉันมีปัญหาเกี่ยวกับการกำกับเสียง (แม้ว่าLC_*ตัวแปรสภาพแวดล้อมของฉันจะถูกตั้งค่าอย่างถูกต้องอย่างเห็นได้ชัด) และเสียงดังทะลุผ่านโค้ดที่มีวันที่จริง sed-fu ของฉันไม่ดีดังนั้นฉันจึงลงเอยด้วยตัวอย่าง frankenstein ที่มีทับทิมอยู่ในนั้น แต่มันใช้ได้ผลกับฉันอย่างไม่มีที่ติบน 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
โปรดทราบด้วยว่าgsedแทนที่จะเป็นsedเพราะนั่นคือการติดตั้งไบนารีของ Homebrew ทำให้ระบบไม่เสียหาย
นี่คือตัวอย่างข้อมูลหลักจากคำตอบของ @Alex ที่จะทำการรวมบรรทัดตำหนิ ฉันตัดมันเพื่อทำงานกับไฟล์เดียวมากกว่าชุดไฟล์
git blame --line-porcelain path/to/file.txt | grep "^author " | sort | uniq -c | sort -nr
ฉันโพสต์ที่นี่เพราะฉันกลับมาที่คำตอบนี้บ่อยครั้งและอ่านโพสต์ซ้ำอีกครั้งและแยกย่อยตัวอย่างเพื่อแยกส่วนที่ฉันให้ความสำคัญกับการเก็บภาษี และมันก็ไม่ธรรมดาสำหรับกรณีการใช้งานของฉัน ขอบเขตสำหรับโครงการ C ทั้งหมด
ฉันชอบที่จะแสดงรายการสถิติต่อไฟล์, ประสบความสำเร็จด้วยการใช้ bash foriterator แทนxargsเพราะฉันพบว่า xargs อ่านได้น้อยลงและใช้งานยาก / จำได้ง่ายข้อดี / ข้อเสียของxargs vsควรได้รับจากที่อื่น
นี่คือตัวอย่างข้อมูลจริงที่จะแสดงผลลัพธ์สำหรับแต่ละไฟล์:
for file in $(git ls-files); do \
echo $file; \
git blame --line-porcelain $file \
| grep "^author " | sort | uniq -c | sort -nr; \
echo; \
done
และฉันทดสอบการใช้ stright นี้ใน bash shell นั้นปลอดภัย ctrl + c ถ้าคุณต้องการใส่มันไว้ในสคริปต์ bash คุณอาจต้องTrap กับ SIGINT และ SIGTERMถ้าคุณต้องการให้ผู้ใช้สามารถทำลายลูปของคุณได้
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 ตรวจจับบรรทัดที่คัดลอกจากไฟล์อื่น ดูเอกสารที่นี่ เพื่อความสมบูรณ์ -w จะละเว้นช่องว่าง
ลองใช้คำสั่ง gitstats จากhttp://gitstats.sourceforge.net/
ฉันมีวิธีแก้ปัญหานี้ที่นับบรรทัดตำหนิในไฟล์ข้อความทั้งหมด (ไม่รวมไฟล์ไบนารี่แม้กระทั่งไฟล์ที่มีเวอร์ชัน):
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
สิ่งนี้ใช้ได้ในไดเรกทอรีใด ๆ ของโครงสร้างซอร์สของ repo ในกรณีที่คุณต้องการตรวจสอบโมดูลซอร์สที่แน่นอน
find . -name '*.c' | xargs -n1 git blame --line-porcelain | grep "^author "|sort|uniq -c|sort -nr
ฉันยอมรับคำตอบยอดนิยมของ 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สวิตช์หรือไม่ฉันเพิ่มมันเพราะไม่สนใจการเปลี่ยนแปลงของช่องว่าง
ประสิทธิภาพในเครื่องของฉันเป็นที่นิยมของ Powershell (~ 50s vs ~ 65s สำหรับ repo เดียวกัน) แม้ว่า Bash solution จะทำงานภายใต้WSL2
สร้างสคริปต์ของตัวเองซึ่งเป็นการรวมกันของ @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กำลังก่อให้เกิดปัญหา .... มันทำงานถูกต้องหรือไม่?
ฟังก์ชัน Bash ที่กำหนดเป้าหมายไฟล์ต้นฉบับไฟล์เดียวที่ทำงานบน MacOS
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
}