วิธีการนับจำนวนบรรทัดทั้งหมดที่เปลี่ยนแปลงโดยผู้เขียนเฉพาะในที่เก็บ Git?


458

มีคำสั่งที่ฉันสามารถเรียกใช้ซึ่งจะนับบรรทัดที่เปลี่ยนแปลงโดยผู้แต่งเฉพาะในที่เก็บ Git หรือไม่? ฉันรู้ว่าต้องมีวิธีนับจำนวนการคอมมิชชันที่ Github ทำกับกราฟผลกระทบ


1
คุณอาจพิจารณาเครื่องมือที่มีชื่อเสียงที่รวบรวมสถิติสำหรับการพัฒนาลินุกซ์เคอร์เนล, git://git.lwn.net/gitdm.gitตัวอย่างเช่นพื้นที่เก็บข้อมูลอยู่ที่นี่
0andriy

คำตอบ:


310

ผลลัพธ์ของคำสั่งต่อไปนี้ควรจะง่ายต่อการส่งไปยังสคริปต์เพื่อเพิ่มผลรวมทั้งหมด:

git log --author="<authorname>" --oneline --shortstat

สิ่งนี้ให้สถิติสำหรับการกระทำทั้งหมดบน HEAD ปัจจุบัน หากคุณต้องการที่จะเพิ่มขึ้นสถิติในสาขาอื่น ๆ git logที่คุณจะต้องจ่ายให้เป็นข้อโต้แย้งที่จะ

สำหรับการส่งผ่านสคริปต์การลบแม้กระทั่งรูปแบบ "ออนไลน์" สามารถทำได้ด้วยรูปแบบบันทึกที่ว่างเปล่าและตามความเห็นของ Jakub Narębski --numstatก็เป็นอีกทางเลือกหนึ่ง มันสร้างต่อไฟล์แทนที่จะเป็นสถิติต่อบรรทัด แต่ง่ายกว่าในการแยกวิเคราะห์

git log --author="<authorname>" --pretty=tformat: --numstat

2
เปลี่ยนคำตอบที่ฉันยอมรับเนื่องจากจะให้ผลลัพธ์ในแบบที่ฉันคาดไว้และจะเป็นประโยชน์มากขึ้นสำหรับผู้เข้าชมรายอื่นที่ต้องการบรรลุเป้าหมาย
Gav

14
คุณสามารถใช้--numstatแทน--shortstatหากคุณต้องการเพิ่มสถิติได้ง่ายขึ้นเล็กน้อย
Jakub Narębski

8
อาจต้องการเพิ่ม "- ไม่รวม" ในที่นั่นด้วย
yoyo

9
ขอโทษสำหรับคำถามนี้ แต่มีตัวเลขอะไรบอกฉัน มีสองแถวและฉันไม่รู้ว่าพวกเขาบอกอะไรฉัน มีเส้น chenged และเพิ่ม?
Informatic0re

2
@ Informatic0re git help logบอกฉันว่าบรรทัดแรกคือการเพิ่มบรรทัดบรรทัดที่สองถูกลบ
ThomasH

599

สิ่งนี้ให้สถิติบางอย่างเกี่ยวกับผู้แต่งแก้ไขตามที่ต้องการ

ใช้ Gawk:

git log --author="_Your_Name_Here_" --pretty=tformat: --numstat \
| gawk '{ add += $1; subs += $2; loc += $1 - $2 } 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 += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -

แก้ไข (2017)

มีแพ็คเกจใหม่บน github ที่ดูเนียนและใช้ bash เป็นการอ้างอิง (ทดสอบบน linux) เหมาะสำหรับการใช้งานโดยตรงมากกว่าสคริปต์

มันคอมไพล์อย่างรวดเร็วสถิติ (ลิงค์ GitHub)

คัดลอกgit-quick-statsไปยังโฟลเดอร์และเพิ่มโฟลเดอร์ไปยังเส้นทาง

mkdir ~/source
cd ~/source
git clone git@github.com: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

ป้อนคำอธิบายรูปภาพที่นี่


18
ขอบคุณสำหรับสายการบินยาวที่น่ารัก! จุดของ awk นี้สำรับดาดฟ้าของทุกคน (แม่นยำถูกต้องไม่มีเอาท์พุตแปลก ๆ ) ไม่น่าแปลกใจเมื่อพิจารณาว่านี่เป็นสิ่งที่น่าแปลกใจที่ออกแบบมาสำหรับ ... น่าเสียดายที่คุณมาปาร์ตี้ช้า
zxq9

4
@ zxq9: ฉันไม่ได้อยู่ใน stackoverflow เมื่อคำถามถูกถามและฉันได้รับแรงบันดาลใจจากคำตอบที่นี่ หวังว่าฉันจะแซงทุกคนที่นี่อย่างช้าๆเพราะผู้คนต้องการสิ่งนี้
อเล็กซ์

9
มันใช้งานได้ดี แต่ฉันต้องเปลี่ยนgawkเพื่อawkให้มันทำงานใน terminal OSX
Zach Lysobey

1
@samthebest เนื่องจากการย้ายไฟล์ไม่ได้สะท้อนถึงสถิติที่เหมาะสม เส้นจะไม่เปลี่ยนแปลง ถึงอเล็กซ์: ฉันกำลังพูดถึง Git Btw ดูความคิดเห็นของฉันกับคำถามเดิม
0andriy

2
หาก url ใช้งานไม่ได้ให้ลอง:git clone https://github.com/arzzen/git-quick-stats.git
Nicolas

226

ในกรณีที่ทุกคนต้องการที่จะเห็นสถิติสำหรับผู้ใช้ทุกคนใน codebase ของพวกเขาเพื่อนร่วมงานของฉันสองคนเพิ่งเกิดขึ้นกับซับในที่น่ากลัวนี้:

git log --shortstat --pretty="%cE" | sed 's/\(.*\)@.*/\1/' | grep -v "^$" | awk 'BEGIN { line=""; } !/^ / { if (line=="" || !match(line, $0)) {line = $0 "," line }} /^ / { print line " # " $0; line=""}' | sort | sed -E 's/# //;s/ files? changed,//;s/([0-9]+) ([0-9]+ deletion)/\1 0 insertions\(+\), \2/;s/\(\+\)$/\(\+\), 0 deletions\(-\)/;s/insertions?\(\+\), //;s/ deletions?\(-\)//' | awk 'BEGIN {name=""; files=0; insertions=0; deletions=0;} {if ($1 != name && name != "") { print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net"; files=0; insertions=0; deletions=0; name=$1; } name=$1; files+=$2; insertions+=$3; deletions+=$4} END {print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net";}'

(ใช้เวลาสองสามนาทีในการกระทืบผ่าน repo ของเราซึ่งมีภาระประมาณ 10-15k)


12
ที่น่ากลัว! michael,: 6057 files changed, 854902 insertions(+), 26973 deletions(-), 827929 net
Michael J. Calkins

1
@EugenKonkov ในรหัสที่กำหนดไว้เป็นส่วนแทรก - ลบ
Dan

13
นั่นเป็นคำสั่งเดียวที่ให้ผลลัพธ์ทั้งหมดสำหรับที่เก็บและรันโดยไม่มีปลั๊กอิน
Ömer Faruk Almalı

1
ฉันได้รับรายชื่อผู้ใช้จำนวนมากรวมกันเกือบทุกชุดที่เป็นไปได้ของนักพัฒนากลับมา ความแปลกประหลาดในตอนท้ายของฉัน?
Damon

2
@BenSewards คุณสามารถใช้ Bash บน Windows โดยใช้ระบบย่อย Windows สำหรับ Linux ข้อมูลเพิ่มเติมได้ที่นี่
mjsr

152

Git fame https://github.com/oleander/git-fame-rb

เป็นเครื่องมือที่ดีในการรับจำนวนผู้เขียนทั้งหมดในครั้งเดียวรวมถึงการคอมมิทและไฟล์ที่ถูกแก้ไข:

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 มาก


1
นี่ช่างยอดเยี่ยม แต่ช้ามาก
Jared Burrows

1
ทำงานได้ดีในกลางปี ​​2015 macbook และโครงการ Android ขนาดกลางขนาดใหญ่ (127k LoC 'is) ไม่กี่นาที.
maxweber

2
@ ร้อยละร้อยละของ toal loc / commits / files สำหรับผู้ใช้ปัจจุบัน
Ciro Santilli 郝海东冠状病六四事件法轮功

1
เปลี่ยนสาขาหมดเวลาและไม่รวมโฟลเดอร์:git fame --branch=dev --timeout=-1 --exclude=Pods/*
jonmecer

1
@AlexanderMills ฉันคาดเดาว่าเป็นเพราะคุณไม่สามารถมีความหมายนับเส้นบน blobs
Ciro Santilli郝海东冠状病六四事件法轮功

103

ฉันพบว่าต่อไปนี้จะเป็นประโยชน์ในการดูว่าใครมีบรรทัดมากที่สุดที่อยู่ในฐานรหัสปัจจุบัน:

git ls-files -z | xargs -0n1 git blame -w | ruby -n -e '$_ =~ /^.*\((.*?)\s[\d]{4}/; puts $1.strip' | sort -f | uniq -c | sort -n

คำตอบอื่น ๆ ส่วนใหญ่มุ่งเน้นไปที่บรรทัดที่เปลี่ยนไปในคอมมิท แต่ถ้าคอมมิทไม่รอดและถูกเขียนทับพวกเขาก็อาจจะปั่นป่วน คาถาข้างต้นยังทำให้คุณได้รับมอบหมายทั้งหมดเรียงตามเส้นแทนที่จะเป็นเพียงหนึ่งครั้ง คุณสามารถเพิ่มตัวเลือกบางอย่างเพื่อตำหนิ git (-C -M) เพื่อให้ได้ตัวเลขที่ดีกว่าซึ่งนำการเคลื่อนไหวของไฟล์และการเคลื่อนไหวของบรรทัดระหว่างไฟล์มาพิจารณา แต่คำสั่งอาจทำงานได้นานขึ้นถ้าคุณทำ

นอกจากนี้หากคุณกำลังมองหาบรรทัดที่เปลี่ยนไปในทุกคอมมิทสำหรับคอมมิชชันทั้งหมดสคริปต์เล็ก ๆ น้อย ๆ ที่ติดตามจะมีประโยชน์

http://git-wt-commit.rubyforge.org/#git-rank-contributors


31
ฉันกำลังจะให้ +1 แต่แล้วฉันก็รู้ว่าโซลูชันขึ้นอยู่กับทับทิม ... :(
mac

3
คุณสามารถแก้ไขมันเพื่อไม่ให้ใช้ทับทิมได้อย่างง่ายดายเพราะฉันใช้ทับทิมแทนค่าสตริง คุณสามารถใช้ perl, sed, python และอื่น ๆ
mmrobins

21
ไม่ทำงานสำหรับฉัน: -e: 1: ใน `<main> ': ลำดับไบต์ที่ไม่ถูกต้องใน UTF-8 (ArgumentError)
MichałDębski

1
/^.*\((.*?)\s[\d]{4}/ควร/^.*?\((.*?)\s[\d]{4}/ป้องกันการจับคู่วงเล็บในแหล่งที่มาในฐานะผู้เขียน
ทิโมธี Gu

1
mmm การประหารชีวิตของฉันแสดงให้เห็นว่ามีผู้ใช้จำนวนมากที่ไม่มีแม้กระทั่งเนื่องจากการแยกวิเคราะห์ไม่ดี ฉันคิดว่ามันไม่ใช่คำตอบที่เชื่อถือได้
mjsr

92

ในการนับจำนวนการกระทำของผู้เขียนที่ได้รับ (หรือผู้เขียนทั้งหมด) ในสาขาที่กำหนดคุณสามารถใช้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

2
โปรดทราบว่าที่v1.6.4นี่ในตัวอย่างนี้เพื่อกำหนดเอาท์พุทกำหนด: มันจะเหมือนกันไม่ว่าเมื่อใดที่คุณโคลนและ / หรือดึงข้อมูลจากที่เก็บ git
Jakub Narębski

รวมถึงv1.6.4ให้ฉัน:fatal: ambiguous argument 'v1.6.4': unknown revision or path not in the working tree.
Vlad the Impala

5
อ่าไม่ฉันพลาด "เมื่อเรียกใช้บนที่เก็บ git" เพื่อความเป็นธรรมคนส่วนใหญ่จะไม่เรียกใช้คำสั่งนี้ใน repo คอมไพล์ โดยกำไรที่ค่อนข้างใหญ่จริงๆ
Vlad the Impala

4
git shortlog -sneหรือหากคุณไม่ต้องการรวมการผสานgit shortlog -sne --no-merges
Mark Swardstrom

1
@Swards: -sถูก--summary, -nเป็น--numberedและ [ใหม่] -eคือ--emailจะแสดงอีเมลของผู้เขียน (และนับแยกผู้เขียนคนเดียวกันกับที่อยู่อีเมลที่แตกต่างกันโดยคำนึงถึง.mailmapการแก้ไข) --no-mergesโทรดีเกี่ยวกับ
Jakub Narębski

75

หลังจากดูคำตอบของ Alexและ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 += $1; subs += $2; loc += $1 - $2 } 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

ไม่สามารถสร้างนามแฝงได้ :-(
brat

33

คำตอบจากAaronMใช้เปลือกหนึ่งซับเป็นสิ่งที่ดี แต่ที่จริงแล้วยังมีข้อผิดพลาดอีกที่ช่องว่างที่จะเสียหายชื่อผู้ใช้หากมีปริมาณที่แตกต่างกันของช่องว่างสีขาวระหว่างชื่อผู้ใช้และวันที่ ชื่อผู้ใช้ที่เสียหายจะให้หลายแถวสำหรับการนับจำนวนผู้ใช้และคุณต้องรวมพวกเขาเอง

การเปลี่ยนแปลงเล็กน้อยนี้แก้ไขปัญหาสำหรับฉัน:

git ls-files -z | xargs -0n1 git blame -w --show-email | perl -n -e '/^.*?\((.*?)\s+[\d]{4}/; print $1,"\n"' | sort -f | uniq -c | sort -n

สังเกตุเครื่องหมาย + หลัง \ s ซึ่งจะใช้ช่องว่างทั้งหมดจากชื่อจนถึงวันที่

จริงๆเพิ่มคำตอบนี้มากสำหรับความทรงจำของฉันเองเพื่อช่วยคนอื่น ๆ เนื่องจากอย่างน้อยครั้งที่สองที่ฉัน google เรื่อง :)

  • แก้ไข 2019-01-23เพิ่ม--show-emailเพื่อgit blame -wรวมในอีเมลแทนเนื่องจากบางคนใช้Nameรูปแบบที่แตกต่างกันในคอมพิวเตอร์ที่แตกต่างกันและบางครั้งคนสองคนที่มีชื่อเดียวกันทำงานในคอมไพล์เดียวกัน

คำตอบที่ใช้ perl นี้ดูเหมือนว่าจะดีกว่าคำตอบทับทิมเล็กน้อย Ruby สำลักในบรรทัดที่ไม่ใช่ข้อความ UTF-8 ที่แท้จริง perl ไม่ได้บ่น แต่ Perl ไม่ทำสิ่งที่ถูกต้องหรือไม่ ฉันไม่รู้
Stéphane Gourichon

Submodules ส่งผลให้เป็นunsupported file typeอย่างอื่น แต่ดูเหมือนว่าจะทำงานได้ดีแม้กับพวกเขา
VladimírČunát

24

ต่อไปนี้เป็นหนึ่งบรรทัดสั้น ๆ ที่สร้างสถิติสำหรับผู้แต่งทั้งหมด มันเร็วกว่าวิธีแก้ปัญหาของ Dan ที่https://stackoverflow.com/a/20414465/1102119 (ฉันมีความซับซ้อนของเวลา O (N) แทน O (NM) โดยที่ N คือจำนวนของความมุ่งมั่นและ M จำนวนผู้เขียน )

git log --no-merges --pretty=format:%an --numstat | awk '/./ && !author { author = $0; next } author { ins[author] += $1; del[author] += $2 } /^$/ { author = ""; next } END { for (a in ins) { printf "%10d %10d %10d %s\n", ins[a] - del[a], ins[a], del[a], a } }' | sort -rn

4
ดี แต่เอาท์พุทหมายถึงอะไร
Gary Willoughby

คุณควรเพิ่ม--no-show-signatureมิฉะนั้นคนที่ pgp-sign จะไม่ถูกนับ
Philihp Busby

2
ins [a] - del [a], ins [a], del [a], a ดังนั้นหากฉันถูกแทรก - ลบ, แทรก, ลบ, ชื่อ
MrKekson

ฉันจะเพิ่มคำสั่งนี้ในการตั้งค่า git ของฉันเพื่อให้สามารถเรียกมันด้วย "git count-lines" ได้อย่างไร?
takanuva15

ไม่เป็นไรฉันคิดออก: count-lines = "!f() { git log --no-merges --pretty=format:%an --numstat | awk '/./ && !author { author = $0; next } author { ins[author] += $1; del[author] += $2 } /^$/ { author = \"\"; next } END { for (a in ins) { printf \"%10d %10d %10d %s\\n\", ins[a] - del[a], ins[a], del[a], a } }' | sort -rn; }; f". (หมายเหตุผมใน Windows คุณอาจจำเป็นต้องใช้ชนิดที่แตกต่างของคำพูด)
takanuva15

21

@mmrobins @AaronM @ErikZ @JamesMishra ระบุตัวแปรที่ทุกคนมีปัญหาร่วมกัน: พวกเขาขอให้คอมไพล์สร้างข้อมูลผสมที่ไม่ได้มีไว้สำหรับการใช้สคริปต์รวมถึงเนื้อหาบรรทัดจากที่เก็บในบรรทัดเดียวกันจากนั้นจับคู่ระเบียบกับ regexp .

นี่เป็นปัญหาเมื่อบางบรรทัดไม่ถูกต้องข้อความ UTF-8 และเมื่อบางบรรทัดเกิดขึ้นเพื่อให้ตรงกับ regexp (เกิดขึ้นที่นี่)

นี่คือสายการแก้ไขที่ไม่มีปัญหาเหล่านี้ มันขอให้คอมไพล์เพื่อเอาท์พุทข้อมูลอย่างสะอาดในบรรทัดที่แยกต่างหากซึ่งทำให้ง่ายต่อการกรองสิ่งที่เราต้องการอย่างแข็งแกร่ง:

git ls-files -z | xargs -0n1 git blame -w --line-porcelain | grep -a "^author " | sort -f | uniq -c | sort -n

คุณสามารถ grep สำหรับสตริงอื่น ๆ เช่นผู้แต่งอีเมลผู้ส่ง ฯลฯ

บางทีอาจจะเป็นครั้งแรกexport LC_ALL=C(สมมติว่าbash) เพื่อบังคับการประมวลผลในระดับไบต์ (สิ่งนี้เกิดขึ้นเพื่อเร่งความเร็ว grep อย่างมากจากโลแคลที่อิง UTF-8)


Nice line ตรงนั้น, เจ๋งมาก, ที่คุณสามารถผสมมันได้อย่างง่ายดาย, แต่สิ่งนี้ล้มเหลวในการทำสิ่งที่โปสเตอร์ดั้งเดิมร้องขอ, นับจำนวนผู้เขียนจากคอมไพล์ แน่ใจว่าคุณสามารถเรียกใช้และทำ wc-l ฯลฯ แต่จากนั้นคุณจะต้องทำซ้ำสำหรับผู้เขียนทุกคนในพื้นที่เก็บข้อมูล
AaronM

1
@AaronM ฉันไม่เข้าใจคำวิจารณ์ของคุณ บรรทัดนี้ AFAIK แสดงผลสถิติเดียวกันกับของคุณเท่านั้นแข็งแกร่งกว่าเท่านั้น ดังนั้นหากคำตอบของฉัน "ล้มเหลวในการทำสิ่งที่ผู้โพสต์ดั้งเดิมร้องขอให้นับโดยผู้เขียนจากคอมไพล์" แล้วของคุณมากยิ่งขึ้น โปรดให้ความกระจ่างแก่ฉัน
Stéphane Gourichon

ขอโทษฉันอ่านผิดฉันคิดว่าต้องแก้ไขคำสั่งสำหรับชื่อผู้แต่งแต่ละชื่อ ความคิดเห็นของคุณเกี่ยวกับ grep สำหรับสายอื่นทำให้ฉันมี แต่มันเป็นความเข้าใจผิดของฉัน
AaronM

มันยอดเยี่ยมมาก ขอบคุณ!
Tek

16

วิธีการแก้ปัญหาที่ได้รับกับทับทิมอยู่ตรงกลาง, Perl จะมีน้อยมากโดยค่าเริ่มต้นที่นี่เป็นทางเลือกที่ใช้ Perl สำหรับบรรทัดปัจจุบันโดยผู้เขียน

git ls-files -z | xargs -0n1 git blame -w | perl -n -e '/^.*\((.*?)\s*[\d]{4}/; print $1,"\n"' | sort -f | uniq -c | sort -n

5
regex ที่อัปเดตไม่ได้สร้างความแตกต่างที่มีความหมายและมันจะหักตามที่คุณไม่ได้หลบเลี่ยง paren แรก อย่างไรก็ตามฉันสามารถเห็นบางกรณีที่คนก่อนหน้าของฉันอาจพบบางบิตในบรรทัดของรหัสที่จะสลักลงบน สิ่งนี้จะทำงานได้อย่างน่าเชื่อถือมากขึ้น: git ls-files -z | xargs -0n1 คอมไพล์ตำหนิ -w | perl -n -e '/^.*?\((.*??\\\\\\\\\ ส่วนที่เหลือของตัวเลขที่พิมพ์ได้ $ 1, "\ n"' | sort -f | uniq -c | sort -n
AaronM

ขอบคุณที่พยายามทำให้ regexp เชื่อถือได้มากขึ้น ดูคำตอบของฉันสำหรับชุดคำสั่งstackoverflow.com/a/36090245/1429390 ที่
Stéphane Gourichon

13

นอกจากคำตอบของ Charles Baileyแล้วคุณอาจต้องการเพิ่ม-Cพารามิเตอร์ลงในคำสั่ง มิฉะนั้นการเปลี่ยนชื่อไฟล์จะนับเป็นการเพิ่มและลบจำนวนมาก (มากเท่ากับไฟล์ที่มีบรรทัด) แม้ว่าเนื้อหาไฟล์จะไม่ถูกแก้ไข

เพื่อแสดงให้เห็นนี่คือความมุ่งมั่นที่มีไฟล์จำนวนมากที่ถูกย้ายไปรอบ ๆ จากหนึ่งในโครงการของฉันเมื่อใช้git log --oneline --shortstatคำสั่ง:

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(-)

ในความคิดของฉันหลังให้มุมมองที่เป็นจริงมากขึ้นของผลกระทบต่อบุคคลที่มีต่อโครงการเนื่องจากการเปลี่ยนชื่อไฟล์เป็นการดำเนินการที่เล็กกว่าการเขียนไฟล์ตั้งแต่เริ่มต้น


2
เมื่อฉันรัน "git log --oneline --shortstat" ฉันไม่ได้รับผลลัพธ์ของคุณ ฉันมีรายการความมุ่งมั่นที่มีจำนวนรุ่น แต่ไม่ใช่จำนวนทั้งหมด ฉันจะรับจำนวนบรรทัดทั้งหมดที่แก้ไขในที่เก็บ git ทั้งหมดได้อย่างไร
เมห์

12

คุณสามารถใช้ 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 <someguy@tensorflow.org>
 585    | somelady <somelady@tensorflow.org>
 212    | niceguy <nice@google.com>
 173    | coolguy <coolgay@google.com>
=====================================================

'คะแนน' หมายถึงอะไร
user11171

@Volte npm i เป็นเพียงช็อตคัตสำหรับการติดตั้ง npm
Michiel

ใช่ฉันรู้แล้ว ฉันต้องมาก่อนชื่อแพคเกจใน-g macOSเพียงแค่พยายามช่วย
Volte

11

ต่อไปนี้เป็นสคริปต์ ruby ​​ด่วนที่สัมพันธ์กับผลกระทบต่อผู้ใช้กับข้อความค้นหาที่ระบุ

ตัวอย่างเช่นสำหรับrubinius :

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

2
สคริปต์นี้ยอดเยี่ยม แต่ไม่รวมผู้แต่งที่มีเพียงบรรทัดเดียวเท่านั้น! หากต้องการแก้ไขให้เปลี่ยนดังนี้: เปลี่ยนแปลงการแทรก = / (\ d +). * (\ d +) การลบ /. แมตช์ (บรรทัด)
Larry Gritz

9

นี่เป็นวิธีที่ดีที่สุดและยังช่วยให้คุณเห็นภาพรวมจำนวนการกระทำทั้งหมดที่ผู้ใช้ทุกคนเห็นได้อย่างชัดเจน

git shortlog -s -n

2
มีประโยชน์ แต่นั่นเป็นจำนวนการไม่รวมบรรทัดโค้ดทั้งหมด
Diolor

5

ฉันให้การแก้ไขคำตอบสั้น ๆ ข้างต้น แต่มันก็ไม่เพียงพอสำหรับความต้องการของฉัน ฉันต้องการเพื่อให้สามารถจัดหมวดหมู่ทั้งบรรทัดที่มุ่งมั่นและบรรทัดในรหัสสุดท้าย ฉันยังต้องการแยกย่อยตามไฟล์ รหัสนี้จะไม่ทำการเรียกคืน แต่จะส่งคืนผลลัพธ์สำหรับไดเรกทอรีเดียว แต่เป็นการเริ่มต้นที่ดีถ้ามีคนต้องการไปเพิ่มเติม คัดลอกและวางลงในไฟล์และทำให้สามารถเรียกใช้หรือเรียกใช้ด้วย 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($1);
        }
        elsif ( $log_line =~ m{^(\d+)\s+(\d+)\s+(.*)} ) {
            my $added = $1;
            my $removed = $2;
            my $file = $3;
            $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 = $1;
            $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};
}

ฉันได้รับข้อผิดพลาดนี้: การหารที่ผิดกฎหมายเป็นศูนย์ที่ x.pl บรรทัด 71
Vivek Jha

จ่าหน้าถึงแผนกที่ผิดกฎหมายโดยศูนย์ในบรรทัดที่ 71. คิดว่ามันจะเกิดขึ้นหากไม่มีการแก้ไข แต่เมื่อไม่นานมานี้ฉันได้เขียนสิ่งนี้
AaronM

2

สำหรับผู้ใช้ windows คุณสามารถใช้ชุดสคริปต์ต่อไปนี้ที่นับจำนวนเพิ่ม / ลบบรรทัดสำหรับผู้เขียนที่ระบุ

@echo off

set added=0
set removed=0

for /f "tokens=1-3 delims= " %%A in ('git log --pretty^=tformat: --numstat --author^=%1') do call :Count %%A %%B %%C

@echo added=%added%
@echo removed=%removed%
goto :eof

:Count
  if NOT "%1" == "-" set /a added=%added% + %1
  if NOT "%2" == "-" set /a removed=%removed% + %2
goto :eof

https://gist.github.com/zVolodymyr/62e78a744d99d414d56646a5e8a1ff4f


2

นี่คือ repo ที่ยอดเยี่ยมที่ทำให้ชีวิตของคุณง่ายขึ้น

git-quick-stats

บน mac ที่ติดตั้ง Brew แล้ว

brew install git-quick-stats

วิ่ง

git-quick-stats

เพียงเลือกตัวเลือกที่คุณต้องการจากรายการนี้โดยพิมพ์หมายเลขที่ปรากฏและกด Enter

 Generate:
    1) Contribution stats (by author)
    2) Contribution stats (by author) on a specific branch
    3) Git changelogs (last 10 days)
    4) Git changelogs by author
    5) My daily status
    6) Save git log output in JSON format

 List:
    7) Branch tree view (last 10)
    8) All branches (sorted by most recent commit)
    9) All contributors (sorted by name)
   10) Git commits per author
   11) Git commits per date
   12) Git commits per month
   13) Git commits per weekday
   14) Git commits per hour
   15) Git commits by author per hour

 Suggest:
   16) Code reviewers (based on git history)


1

สคริปต์นี้ที่นี่จะทำมัน ใส่ไว้ใน 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 ":"

1
ไม่ WONT! คุณโพสต์สิ่งนี้ที่อื่นมันสร้างข้อผิดพลาดบน macs และ linux คุณรู้ไหมว่าคอมพิวเตอร
Pizzaiola Gorgonzola

1

บันทึกบันทึกของคุณลงในไฟล์โดยใช้:

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

0

คุณต้องการGit ตำหนิ

มีตัวเลือก --show-stats ที่จะพิมพ์ได้ดีสถิติ


ฉันพยายามblameแต่มันไม่ได้ให้สถิติที่ฉันคิดว่า OP ต้องการหรือไม่
CB Bailey

ขอบคุณสิ่งนี้ก็ช่วยฉันด้วย. mapmap เช่นกัน!
Gav

0

คำถามที่ถามหาข้อมูลเกี่ยวกับผู้เขียนที่เฉพาะเจาะจงแต่คำตอบจำนวนมากเป็นวิธีการแก้ปัญหาที่ส่งกลับรายชื่อผู้เขียนอันดับตามบรรทัดรหัสของพวกเขาเปลี่ยนไป

นี่คือสิ่งที่ฉันกำลังมองหา แต่โซลูชั่นที่มีอยู่ไม่ได้ค่อนข้างสมบูรณ์แบบ เพื่อประโยชน์ของผู้คนที่อาจพบคำถามนี้ผ่านทาง Google ฉันได้ทำการปรับปรุงบางอย่างและทำให้พวกเขากลายเป็นเชลล์สคริปต์ซึ่งฉันแสดงไว้ด้านล่าง หนึ่งข้อเขียน (ซึ่งผมจะยังคงรักษา) สามารถพบได้บน Github

ขณะนี้ไม่มีการอ้างอิงทั้ง Perl หรือทับทิม นอกจากนี้ช่องว่างการเปลี่ยนชื่อและการเคลื่อนไหวของเส้นจะถูกนำมาพิจารณาในการนับการเปลี่ยนแปลงบรรทัด ใส่สิ่งนี้ลงในไฟล์และส่งที่เก็บ Git ของคุณเป็นพารามิเตอร์แรก

#!/bin/bash
git --git-dir="$1/.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="$1" --git-dir="$1/.git" ls-files -z |\
    xargs -0n1 git --work-tree="$1" --git-dir="$1/.git" blame -C -M  -w |\
    cut -d'(' -f2 |\
    cut -d2 -f1 |\
    sed -e "s/ \{1,\}$//" |\
    sort |\
    uniq -c |\
    sort -nr
fi

0

เครื่องมือที่ดีที่สุดที่ฉันระบุคือ 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

0

ฉันเขียนสคริปต์ Perl นี้เพื่อทำงานให้สำเร็จ

#!/usr/bin/env perl

use strict;
use warnings;

# save the args to pass to the git log command
my $ARGS = join(' ', @ARGV);

#get the repo slug
my $NAME = _get_repo_slug();

#get list of authors
my @authors = _get_authors();
my ($projectFiles, $projectInsertions, $projectDeletions) = (0,0,0);
#for each author
foreach my $author (@authors) {
  my $command = qq{git log $ARGS --author="$author" --oneline --shortstat --no-merges};
  my ($files, $insertions, $deletions) = (0,0,0);
  my @lines = `$command`;
  foreach my $line (@lines) {
    if ($line =~ m/^\s(\d+)\s\w+\s\w+,\s(\d+)\s\w+\([\+|\-]\),\s(\d+)\s\w+\([\+|\-]\)$|^\s(\d+)\s\w+\s\w+,\s(\d+)\s\w+\(([\+|\-])\)$/) {
      my $lineFiles = $1 ? $1 : $4;
      my $lineInsertions = (defined $6 && $6 eq '+') ? $5 : (defined $2) ? $2 : 0;
      my $lineDeletions = (defined $6 && $6 eq '-') ? $5 : (defined $3) ? $3 : 0;
      $files += $lineFiles;
      $insertions += $lineInsertions;
      $deletions += $lineDeletions;
      $projectFiles += $lineFiles;
      $projectInsertions += $lineInsertions;
      $projectDeletions += $lineDeletions;
    }
  }
  if ($files || $insertions || $deletions) {
    printf(
      "%s,%s,%s,+%s,-%s,%s\n",
      $NAME,
      $author,
      $files,
      $insertions,
      $deletions,
      $insertions - $deletions
    );
  }
}

printf(
  "%s,%s,%s,+%s,-%s,%s\n",
  $NAME,
  'PROJECT_TOTAL',
  $projectFiles,
  $projectInsertions,
  $projectDeletions,
  $projectInsertions - $projectDeletions
);

exit 0;

#get the remote.origin.url joins that last two pieces (project and repo folder)
#and removes any .git from the results. 
sub _get_repo_slug {
  my $get_remote_url = "git config --get remote.origin.url";
  my $remote_url = `$get_remote_url`;
  chomp $remote_url;

  my @parts = split('/', $remote_url);

  my $slug = join('-', @parts[-2..-1]);
  $slug =~ s/\.git//;

  return $slug;
}

sub _get_authors {
  my $git_authors = 'git shortlog -s | cut -c8-';
  my @authors = `$git_authors`;
  chomp @authors;

  return @authors;
}

ผมตั้งชื่อมันและใส่ลงในgit-line-changes-by-author /usr/local/binเนื่องจากมันถูกบันทึกไว้ในเส้นทางของฉันฉันสามารถออกคำสั่งgit line-changes-by-author --before 2018-12-31 --after 2020-01-01เพื่อรับรายงานสำหรับปี 2019 ตัวอย่างเช่น. และถ้าฉันจะสะกดคำผิด git ชื่อจะแนะนำการสะกดที่เหมาะสม

คุณอาจต้องการปรับ_get_repo_slugย่อยเพื่อรวมเฉพาะส่วนสุดท้ายของรายการremote.origin.urlบันทึกของฉันเป็นproject/repoและคุณอาจไม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.