Làm cách nào để đếm tổng số dòng được thay đổi bởi một tác giả cụ thể trong kho Git?


458

Có một lệnh tôi có thể gọi để đếm các dòng được thay đổi bởi một tác giả cụ thể trong kho Git không? Tôi biết rằng phải có nhiều cách để đếm số lượng cam kết khi Github thực hiện điều này cho biểu đồ Tác động của họ.


1
Bạn có thể xem xét công cụ nổi tiếng thu thập số liệu thống kê để phát triển nhân Linux, ví dụ: Kho lưu trữ ở đây git://git.lwn.net/gitdm.git.
0andriy

Câu trả lời:


310

Đầu ra của lệnh sau phải dễ dàng gửi đến tập lệnh để thêm tổng số:

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

Điều này cung cấp số liệu thống kê cho tất cả các cam kết trên ĐẦU hiện tại. Nếu bạn muốn thêm số liệu thống kê trong các nhánh khác, bạn sẽ phải cung cấp chúng làm đối số git log.

Để chuyển đến một tập lệnh, loại bỏ ngay cả định dạng "trực tuyến" có thể được thực hiện với định dạng nhật ký trống và như nhận xét của Jakub Narębski, --numstatlà một cách khác. Nó tạo ra mỗi tệp chứ không phải thống kê trên mỗi dòng nhưng thậm chí còn dễ phân tích hơn.

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

2
Đã thay đổi câu trả lời được chấp nhận của tôi vì điều này mang lại đầu ra theo cách tôi mong đợi và sẽ hữu ích hơn cho những khách truy cập khác muốn đạt được điều này.
Gav

14
Bạn có thể sử dụng --numstatthay vì --shortstatnếu bạn muốn thêm số liệu thống kê dễ dàng hơn một chút.
Jakub Narębski

8
Cũng có thể muốn thêm "--no-sáp nhập" vào đó.
yoyo

9
xin lỗi vì câu hỏi này, nhưng những con số nói với tôi là gì? Có hai hàng và tôi không biết họ đang nói gì với tôi. Dòng chenged và thêm?
Informatic0re

2
@ Informatic0re git help logcho tôi biết rằng dòng đầu tiên được thêm vào, dòng thứ hai bị xóa.
ThomasH

599

Điều này cung cấp một số thống kê về tác giả, sửa đổi theo yêu cầu.

Sử dụng 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 }' -

Sử dụng Awk trên 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 }' -

EDIT (2017)

Có một gói mới trên github trông bóng bẩy và sử dụng bash làm phụ thuộc (được thử nghiệm trên linux). Nó phù hợp hơn cho việc sử dụng trực tiếp hơn là các tập lệnh.

Đó là git-quick-stats (liên kết github) .

Sao chép git-quick-statsvào một thư mục và thêm thư mục vào đường dẫn.

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

Sử dụng:

git-quick-stats

nhập mô tả hình ảnh ở đây


18
Cảm ơn cho lót dài đáng yêu này! Điểm này của awk đã quét sạch bộ bài của mọi người (chính xác, nhanh chóng, không có đầu ra kỳ lạ nào). Không có gì đáng ngạc nhiên, coi đây là loại điều mà awk được thiết kế cho ... Thật tệ là bạn đã đến bữa tiệc quá muộn.
zxq9

4
@ zxq9: Tôi thậm chí không ở stackoverflow khi câu hỏi được hỏi và tôi được truyền cảm hứng bởi các câu trả lời ở đây. hãy hy vọng tôi sẽ dần vượt qua mọi người ở đây vì mọi người cứ cần điều này.
Alex

9
Này hoạt động tuyệt vời, nhưng tôi đã phải thay đổi gawkđể awklàm cho nó hoạt động tại nhà ga OSX
Zach Lysobey

1
@samthebest, vì di chuyển tệp không phản ánh số liệu thống kê phù hợp. Các dòng không thay đổi. Gửi Alex: Tôi đang nói về Git. Btw, xem bình luận của tôi cho câu hỏi ban đầu.
0andriy

2
Nếu url không phù hợp với bạn, hãy thử điều này:git clone https://github.com/arzzen/git-quick-stats.git
Nicolas

226

Trong trường hợp bất cứ ai muốn xem số liệu thống kê cho mọi người dùng trong cơ sở mã của họ, một vài đồng nghiệp của tôi gần đây đã đưa ra một lớp lót khủng khiếp này:

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";}'

(Mất vài phút để truy cập vào repo của chúng tôi, có khoảng 10-15k cam kết.)


12
Thật tuyệt vời! michael,: 6057 files changed, 854902 insertions(+), 26973 deletions(-), 827929 net
Michael J. Calkins 17/12/13

1
@EugenKonkov trong mã được định nghĩa là phần chèn thêm - xóa.
Dan

13
đó là lệnh duy nhất cung cấp tổng kết quả cho kho lưu trữ và chạy mà không cần bất kỳ plugin nào.
Ömer Faruk Almalı

1
Tôi đang có một nhóm người dùng được liệt kê cùng nhau, gần như mọi sự kết hợp có thể có của các nhà phát triển sẽ quay trở lại. sự kỳ lạ về kết thúc của tôi?
Damon

2
@BenSewards bạn có thể sử dụng Bash trên Windows bằng Hệ thống con Windows cho Linux, thông tin thêm ở đây
mjsr

152

Danh tiếng Git https://github.com/oleander/git-fame-rb

là một công cụ tuyệt vời để lấy số lượng cho tất cả các tác giả cùng một lúc, bao gồm số lượng tệp cam kết và sửa đổi:

sudo apt-get install ruby-dev
sudo gem install git_fame
cd /path/to/gitdir && git fame

Ngoài ra còn có phiên bản Python tại https://github.com/casperdcl/git-fame (được đề cập bởi @fracz):

sudo apt-get install python-pip python-dev build-essential 
pip install --user git-fame
cd /path/to/gitdir && git fame

Đầu ra mẫu:

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    |
+------------------------+--------+---------+-------+--------------------+

Nhưng hãy cảnh báo: như Jared đã đề cập trong bình luận, thực hiện nó trên một kho lưu trữ rất lớn sẽ mất nhiều giờ. Không chắc chắn nếu điều đó có thể được cải thiện, xem xét rằng nó phải xử lý rất nhiều dữ liệu Git.


1
Điều này thật tuyệt vời nhưng rất chậm
Jared Burrows

1
Hoạt động tốt trên macbook giữa năm 2015 và dự án Android cỡ trung bình (127k LoC 'là). Vài phút.
maxweber

2
@Vincent phần trăm của định vị / cam kết / tệp cho người dùng hiện tại.
Ciro Santilli 郝海东 冠状 病 事件 8/12/15

1
Thay đổi chi nhánh, thời gian chờ và loại trừ một thư mục:git fame --branch=dev --timeout=-1 --exclude=Pods/*
jonmecer

1
@AlexanderMills Tôi đoán là vì bạn không thể đếm số dòng trên blobs một cách có ý nghĩa
Ciro Santilli 冠状 病 六四

103

Tôi thấy những điều sau đây là hữu ích để xem ai có nhiều dòng nhất trong cơ sở mã:

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

Các câu trả lời khác chủ yếu tập trung vào các dòng thay đổi trong các cam kết, nhưng nếu các cam kết không tồn tại và bị ghi đè, chúng có thể đã bị đảo lộn. Câu thần chú trên cũng giúp bạn có tất cả các ủy viên được sắp xếp theo dòng thay vì chỉ một lần. Bạn có thể thêm một số tùy chọn để git đổ lỗi (-C -M) để có được một số số tốt hơn giúp di chuyển tệp và chuyển động dòng giữa các tệp vào tài khoản, nhưng lệnh có thể chạy lâu hơn nếu bạn làm như vậy.

Ngoài ra, nếu bạn đang tìm kiếm các dòng thay đổi trong tất cả các cam kết cho tất cả các ủy viên, tập lệnh nhỏ theo sau là hữu ích:

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


31
Tôi chuẩn bị cho +1, nhưng sau đó tôi nhận ra rằng giải pháp đó phụ thuộc vào ruby ​​... :(
mac

3
Bạn có thể sửa đổi nó để không sử dụng ruby ​​khá dễ dàng vì tôi chỉ sử dụng ruby ​​để thay thế chuỗi. Bạn có thể sử dụng perl, sed, python, v.v.
mmrobin

21
không hoạt động với tôi: -e: 1: in `<main> ': chuỗi byte không hợp lệ trong UTF-8 (ArgumentError)
Michał Dbski

1
/^.*\((.*?)\s[\d]{4}/nên /^.*?\((.*?)\s[\d]{4}/để ngăn chặn dấu ngoặc đơn trong nguồn với tư cách là một tác giả.
Timothy Gu

1
mmm thực thi của tôi cho thấy rất nhiều người dùng thậm chí không tồn tại, do phân tích cú pháp xấu. Tôi nghĩ đó không phải là một câu trả lời đáng tin cậy.
mjsr

92

Để đếm số lượng cam kết của một tác giả nhất định (hoặc tất cả các tác giả) trên một nhánh nhất định, bạn có thể sử dụng git-shortlog ; đặc biệt là xem các tùy chọn --numbered--summarytùy chọn của nó , ví dụ như khi chạy trên kho 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
Lưu ý rằng v1.6.4ở đây trong ví dụ này để xác định đầu ra: nó sẽ giống nhau bất kể khi nào bạn sao chép và / hoặc tìm nạp từ kho git.
Jakub Narębski

bao gồm cả v1.6.4cho tôi:fatal: ambiguous argument 'v1.6.4': unknown revision or path not in the working tree.
Vlad the Impala

5
À, không, tôi đã bỏ lỡ "khi chạy trên kho git". Để công bằng, hầu hết mọi người sẽ không chạy lệnh này trên repo git. Bởi một biên độ khá lớn, thực sự.
Vlad the Impala

4
git shortlog -snehoặc, nếu bạn không bao gồm các sự hợp nhấtgit shortlog -sne --no-merges
Mark Swardstrom

1
@Swards: -sis --summary, -nis --numberedvà [new] -e--emailhiển thị email của các tác giả (và tính riêng biệt cùng một tác giả với địa chỉ email khác nhau, có tính đến .mailmapchỉnh sửa tài khoản ). Gọi tốt về --no-merges.
Jakub Narębski

75

Sau khi nhìn vào Alex'sGerty3000 câu trả lời , tôi đã cố gắng rút ngắn phần một:

Về cơ bản, sử dụng git log numstat và không theo dõi số lượng tệp đã thay đổi.

Phiên bản Git 2.1.0 trên 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

Thí dụ:

Jared Burrows   added lines: 6826, removed lines: 2825, total lines: 4001

Không thể tạo bí danh cho nó :-(
brat

33

Câu trả lời từ AaronM sử dụng shell one-liner là tốt, nhưng thực tế, vẫn còn một lỗi khác, trong đó khoảng trắng sẽ làm hỏng tên người dùng nếu có số lượng khoảng trắng khác nhau giữa tên người dùng và ngày. Tên người dùng bị hỏng sẽ cung cấp nhiều hàng cho số lượng người dùng và bạn phải tự tổng hợp chúng.

Thay đổi nhỏ này đã khắc phục sự cố cho tôi:

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

Lưu ý + sau \ s sẽ tiêu thụ tất cả các khoảng trắng từ tên đến ngày.

Trên thực tế, việc thêm câu trả lời này cho sự ghi nhớ của riêng tôi cũng như giúp đỡ bất kỳ ai khác, vì đây ít nhất là lần thứ hai tôi google chủ đề :)

  • Chỉnh sửa 2019-01-23 Đã thêm vào --show-emailđể git blame -wtổng hợp trên email, vì một số người sử dụng các Nameđịnh dạng khác nhau trên các máy tính khác nhau và đôi khi hai người có cùng tên đang làm việc trong cùng một git.

Câu trả lời này sử dụng perl có vẻ tốt hơn một chút so với những người dựa trên ruby. Ruby nghẹn ngào trên những dòng không phải là văn bản UTF-8 thực tế, perl đã không phàn nàn. Nhưng perl đã làm đúng? Tôi không biết.
Stéphane Gourichon 18/03/2016

Submodules dẫn đến unsupported file typenhưng nếu không thì nó có vẻ hoạt động tốt ngay cả với chúng (nó bỏ qua chúng).
Vladimír Čunát

24

Đây là một lớp lót ngắn tạo ra số liệu thống kê cho tất cả các tác giả. Nó nhanh hơn nhiều so với giải pháp của Dan ở trên tại https://stackoverflow.com/a/20414465/1102119 (của tôi có độ phức tạp thời gian O (N) thay vì O (NM) trong đó N là số lượng cam kết và M là số lượng tác giả ).

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
Đẹp nhưng đầu ra có nghĩa là gì?
Gary Willoughby

Bạn nên thêm --no-show-signature, nếu không, những người đăng ký cam kết của họ sẽ không được tính.
Philihp Busby

2
in [a] - del [a], ins [a], del [a], a, vì vậy nếu tôi đúng chèn - xóa, chèn, xóa, đặt tên
MrKekson

Làm cách nào tôi có thể thêm lệnh này vào cấu hình git của mình để tôi có thể gọi nó bằng "git Count-lines"?
takanuva15

Không sao, tôi đã hiểu ra rồi : 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". (Lưu ý tôi đang dùng Windows; bạn có thể cần sử dụng các loại trích dẫn khác nhau)
takanuva15

21

@mmrobins @AaronM @ErikZ @JamesMishra cung cấp các biến thể mà tất cả đều có vấn đề chung: họ yêu cầu git tạo ra một hỗn hợp thông tin không dành cho tiêu thụ tập lệnh, bao gồm nội dung dòng từ kho lưu trữ trên cùng một dòng, sau đó khớp với mớ hỗn độn với regrec .

Đây là một vấn đề khi một số dòng không hợp lệ văn bản UTF-8 và cả khi một số dòng xảy ra khớp với biểu thức chính quy (điều này đã xảy ra ở đây).

Đây là một dòng sửa đổi không có những vấn đề này. Nó yêu cầu git xuất dữ liệu sạch trên các dòng riêng biệt, giúp dễ dàng lọc những gì chúng ta muốn một cách mạnh mẽ:

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

Bạn có thể grep cho các chuỗi khác, như tác giả-mail, committer, v.v.

Có lẽ trước tiên phải export LC_ALL=C(giả sử bash) để buộc xử lý mức byte (điều này cũng xảy ra để tăng tốc grep rất nhiều từ các địa phương dựa trên UTF-8).


Dòng tuyệt vời ở đó, rất tuyệt, mà bạn có thể dễ dàng trộn nó lên, tuy nhiên điều này không thực hiện được những gì người đăng ban đầu yêu cầu, cung cấp số lượng của tác giả từ git. Chắc chắn bạn có thể chạy nó và thực hiện wc-l, v.v., nhưng sau đó bạn sẽ cần lặp lại cho mọi tác giả trong kho lưu trữ.
AaronM

1
@AaronM Tôi không hiểu những lời chỉ trích của bạn. Dòng AFAIK này đưa ra số liệu thống kê giống như của bạn, chỉ mạnh mẽ hơn. Vì vậy, nếu câu trả lời của tôi "không thực hiện được những gì người đăng ban đầu yêu cầu, hãy cung cấp số lượng theo tác giả từ git", thì bạn thậm chí còn nhiều hơn thế. Vui lòng làm sáng tỏ cho tôi.
Stéphane Gourichon

xin lỗi tôi đã đọc sai, tôi nghĩ rằng lệnh phải được sửa đổi cho mỗi tên tác giả khác nhau. Nhận xét của bạn về grep cho các chuỗi khác dẫn tôi đến đó nhưng đó là sự hiểu lầm của tôi.
AaronM

Việc này thật là tuyệt. Cảm ơn!
Tek

16

Một giải pháp đã được đưa ra với ruby ​​ở giữa, perl có sẵn hơn một chút theo mặc định ở đây là một thay thế sử dụng perl cho các dòng hiện tại của tác giả.

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 cập nhật không tạo ra sự khác biệt có ý nghĩa và nó bị phá vỡ khi bạn không thoát khỏi paren đầu tiên. Tuy nhiên, tôi có thể thấy một số trường hợp trong đó trường hợp trước của tôi có thể tìm thấy một số bit trong dòng mã để chốt. Điều này sẽ hoạt động đáng tin cậy hơn: git ls-files -z | xargs -0n1 git đổ lỗi -w | perl -n -e '/ ^. ^? ^ ((. *?) \ s [\ [mệnh đề44 / in $ 1, "\ n"' | sort -f | uniq -c | sort -n
AaronM

cảm ơn vì đã cố gắng tạo ra một bản khai thác đáng tin cậy hơn. Xem câu trả lời của tôi cho một stackoverflow
hơn.com / a / 36090245/429390

13

Ngoài câu trả lời của Charles Bailey , bạn có thể muốn thêm -Ctham số vào các lệnh. Mặt khác, đổi tên tệp được tính là rất nhiều bổ sung và loại bỏ (nhiều như tệp có dòng), ngay cả khi nội dung tệp không được sửa đổi.

Để minh họa, đây là một cam kết với rất nhiều tệp được di chuyển xung quanh từ một trong các dự án của tôi, khi sử dụng git log --oneline --shortstatlệnh:

9052459 Reorganized project structure
 43 files changed, 1049 insertions(+), 1000 deletions(-)

Và ở đây, cùng một cam kết sử dụng git log --oneline --shortstat -Clệnh phát hiện các bản sao và đổi tên tệp:

9052459 Reorganized project structure
 27 files changed, 134 insertions(+), 85 deletions(-)

Theo ý kiến ​​của tôi, cái sau đưa ra một cái nhìn thực tế hơn về mức độ ảnh hưởng của một người đối với dự án, bởi vì đổi tên một tệp là một hoạt động nhỏ hơn nhiều so với việc viết tệp từ đầu.


2
Khi tôi thực hiện "git log --oneline --shortstat", tôi không nhận được kết quả của bạn. Tôi có một danh sách các cam kết với số lượng phiên bản nhưng không phải là tổng số. Làm thế nào tôi có thể nhận được tổng số dòng được chỉnh sửa trong tất cả các kho git?
Mehdi

12

bạn có thể sử dụng 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

hoặc chỉ gõ

$ whodid

sau đó bạn có thể thấy kết quả như thế này

Contribution state
=====================================================
 score  | author
-----------------------------------------------------
 3059   | someguy <someguy@tensorflow.org>
 585    | somelady <somelady@tensorflow.org>
 212    | niceguy <nice@google.com>
 173    | coolguy <coolgay@google.com>
=====================================================

"Điểm số" nghĩa là gì?
dùng11171

@Volte npm tôi chỉ là một lối tắt để cài đặt npm
Michiel

Vâng, tôi biết. Tôi -gđã phải đến trước tên gói, trên macOS. Đơn giản chỉ cần cố gắng để giúp đỡ.
Volte

11

Đây là một tập lệnh ruby ​​nhanh giúp điều chỉnh tác động của mỗi người dùng đối với một truy vấn nhật ký đã cho.

Ví dụ: đối với rubinius :

Brian Ford: 4410668
Evan Phoenix: 1906343
Ryan Davis: 855674
Shane Becker: 242904
Alexander Kellett: 167600
Eric Hodel: 132986
Dirkjan Bussink: 113756
...

kịch bản:

#!/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
Kịch bản này là tuyệt vời, nhưng loại trừ các tác giả chỉ có các cam kết một dòng! Để khắc phục, thay đổi như sau: thay đổi = / (\ d +) chèn. * (\ D +) xóa / .match (dòng)
Larry Gritz

9

đây là cách tốt nhất và nó cũng cho bạn một bức tranh rõ ràng về tổng số lần cam kết của tất cả người dùng

git shortlog -s -n

2
Hữu ích, nhưng đó là số lần xác nhận không phải là tổng số dòng mã
Diolor

5

Tôi đã cung cấp một sửa đổi của một câu trả lời ngắn ở trên, nhưng nó không đủ cho nhu cầu của tôi. Tôi cần để có thể phân loại cả dòng và dòng cam kết trong mã cuối cùng. Tôi cũng muốn chia nhỏ theo tập tin. Mã này không lặp lại, nó sẽ chỉ trả về kết quả cho một thư mục duy nhất, nhưng đó là một khởi đầu tốt nếu ai đó muốn đi xa hơn. Sao chép và dán vào một tệp và thực hiện hoặc chạy nó với 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};
}

Tôi nhận được lỗi này: Phân chia bất hợp pháp cho số 0 tại x.pl dòng 71.
Vivek Jha

Đã giải quyết sự phân chia bất hợp pháp bằng số 0 trên dòng 71. Hãy nghĩ rằng nó xảy ra nếu không có chỉnh sửa nhưng cách đây một thời gian tôi đã viết bài này.
AaronM

2

Đối với người dùng windows, bạn có thể sử dụng tập lệnh bó sau để đếm các dòng được thêm / xóa cho tác giả được chỉ định

@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

Đây là một repo tuyệt vời làm cho cuộc sống của bạn dễ dàng hơn

git-quick-stats

Trên máy mac có cài đặt brew

brew install git-quick-stats

Chạy

git-quick-stats

Chỉ cần chọn tùy chọn bạn muốn từ danh sách này bằng cách nhập số được liệt kê và nhấn 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

Kịch bản này ở đây sẽ làm điều đó. Đặt nó vào quyền tác giả.sh, chmod + x nó và bạn đã hoàn tất.

#!/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
không, nó KHÔNG!, bạn đã đăng cái này ở nơi khác, nó tạo ra lỗi trên máy Mac và linux, bạn biết đấy, loại máy tính git đã được tạo ra!
Pizzaiola Gorgonzola

1

Lưu nhật ký của bạn vào tệp bằng cách sử dụng:

git log --author="<authorname>" --oneline --shortstat > logs.txt

Dành cho những người yêu thích Python:

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

Kết quả đầu ra của bạn sẽ như sau:

225        files changed
6751       insertions
1379       deletions

0

Bạn muốn Git đổ lỗi .

Có một tùy chọn --show-stats để in một số, tốt, thống kê.


Tôi đã thử blame, nhưng nó không thực sự đưa ra số liệu thống kê mà tôi nghĩ OP sẽ cần?
CB Bailey

Cảm ơn, điều này cũng giúp tôi với .mailmap quá!

0

Câu hỏi yêu cầu thông tin về một cụ thể tác giả , nhưng nhiều câu trả lời là các giải pháp trả về danh sách xếp hạng của các tác giả dựa trên các dòng mã của họ đã thay đổi.

Đây là những gì tôi đang tìm kiếm, nhưng các giải pháp hiện tại không hoàn hảo. Vì lợi ích của những người có thể tìm thấy câu hỏi này thông qua Google, tôi đã thực hiện một số cải tiến về chúng và biến chúng thành tập lệnh shell, mà tôi hiển thị bên dưới. Một chú thích (mà tôi sẽ tiếp tục duy trì) có thể được tìm thấy trên Github của tôi .

Không sự phụ thuộc vào Perl hoặc Ruby. Hơn nữa, khoảng trắng, đổi tên và chuyển động của dòng được tính đến trong số lượng thay đổi dòng. Chỉ cần đặt nó vào một tệp và vượt qua kho Git của bạn làm tham số đầu tiên.

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

Công cụ tốt nhất cho đến nay tôi xác định là gitinspector. Nó cung cấp báo cáo được thiết lập cho mỗi người dùng, mỗi tuần, v.v. Bạn có thể cài đặt như bên dưới với npm

cài đặt npm -g gitinspector

Các liên kết để có thêm thông tin chi tiết

https://www.npmjs.com/package/gitinspector

https://github.com/ejwa/gitinspector/wiki/Documentation

https://github.com/ejwa/gitinspector

các lệnh ví dụ là

gitinspector -lmrTw 
gitinspector --since=1-1-2017 etc

0

Tôi đã viết kịch bản Perl này để hoàn thành nhiệm vụ đó.

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

Tôi đặt tên cho nó git-line-changes-by-authorvà đưa vào /usr/local/bin. Vì nó được lưu trong đường dẫn của tôi, tôi có thể ra lệnh git line-changes-by-author --before 2018-12-31 --after 2020-01-01để nhận báo cáo cho năm 2019. Làm ví dụ Và nếu tôi viết sai chính tả, tên git sẽ gợi ý cách viết đúng.

Bạn có thể muốn điều chỉnh _get_repo_slugphụ để chỉ bao gồm phần cuối cùng vì các remote.origin.urlrepos của tôi được lưu dưới dạng project/repovà có thể không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.