1. 程式人生 > >統計一下專案中的程式碼有多少行是你貢獻的

統計一下專案中的程式碼有多少行是你貢獻的


文章目錄


本篇內容僅對 Linux/Mac 友好,Windows 開發者請勿介意。

在一個有多人蔘與過的專案中,不知道其他人有沒有和我一樣會去想:當前這個專案有多少行程式碼是我寫的,有多少行程式碼是其他人寫的?

方法一

我們知道,git blame 的命令可以檢視一個檔案的每一行程式碼的最終修改者,如下:

git ls-files 可以列出所有提交到 git 上的檔案。那麼組合這兩個命令,再加上 grep sort uniq 等其他命令,過濾出作者資訊並統計排序,就可以得出結果了。

Ubuntu

下面是在 ubuntu 上的程式碼:

for file in `git ls-files |grep -P "(\.xml)|(\.java)|(\.md)|(\.gradle)|(\.kt)"`; do git blame -c $file |perl -pe 's/^[^\(]+\(\s*+([^\s]+)\s.+/\1/g'; done |sort |uniq -c |
sort -rn

這裡解釋一下。Ubuntu 的 grep 需要加 -P 引數才能使用複雜的正則表示式。由於是 Android 專案,所以這裡只過濾出 xml、java、markdown、gradle 及 kotlin 檔案,然後使用 git blame -c 檢視每一行的作者,它的格式是這樣的:

81f173a6d9      (      msdx     2018-11-02 12:20:37 +0800       22)        classpath 'com.githang:fir:0.6'
73b2575d2d      (      msdx     2018-10-17 17:12:08 +0800       23)
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.71' 73b2575d2d ( msdx 2018-10-17 17:12:08 +0800 24) classpath 'org.jetbrains.kotlin:kotlin-android-extensions:1.2.71' 8c59994eec ( msdx 2018-02-23 14:21:54 +0800 25) classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'

所以使用 perl 命令把中間的作者名稱過濾出來。這裡 perl 的使用與 sed 類似。然後是迴圈結束,這時候輸出的是每一行的作者,所以使用 sort 按作者進行排序,再使用 uniq -c 統計每個作者出現的次數,最後再使用 sort -rn 按次數由大到小進行排序,最終得出結果如下:

48353 msdx
1114 huangxingwei
 401 lixiaoqiang
  92 huanghaohang
  48 yoojia.chen

Mac

上面的命令,在 Mac 上使用 grep -P 引數並沒有效果,所以我調整為分別使用 -e 指定包含的檔名,最終指令碼如下:

for file in `git ls-files |grep -e "\.xml" -e "\.java" -e "\.md" -e "\.gradle" -e "\.kt"`; do git blame -c $file |perl -pe 's/^[^\(]+\(\s*+([^\s]+)\s.+/\1/g'; done |sort| uniq -c |sort -rn

方法二

上面是自己想的辦法。但如果在 Ubuntu 使用 man git blame 檢視過 git blame 的幫助文件的話,會發現官方文件上提供了另一種檢視統計每個作者貢獻行數的方法,如下:

# count the number of lines attributed to each author
git blame --line-porcelain file |
sed -n 's/^author //p' |
sort | uniq -c | sort -rn

所以我們把上面指令碼中的迴圈體內容換成這裡的方式,就不用寫那麼複雜的過濾作者正則表示式了。

Ubuntu

Ubuntu 下命令如下:

for file in `git ls-fles |grep -P "(\.xml)|(\.java)|(\.md)|(\.gradle)|(\.kt)"`; do git blame --line-porcelain $file |sed -n 's/^author //p'; done |sort |uniq -c |sort -rn

Mac

對應的,Mac 的命令修改如下:

for file in `git ls-files |grep -e "\.xml" -e "\.java" -e "\.md" -e "\.gradle" -e "\.kt"`; do git blame --line-porcelain $file|sed -n 's/^author //p'; done |sort |uniq -c |sort -rn

同一作者不同名稱的問題

你可能會發現一個問題,這兩種統計都依賴於提交時的作者資訊,如果在不同維護時期設定的作者及郵件不同,那麼就會統計成不同的人出來。比如前面的 msdxhuanghaohang 都是我一個人。那麼應該如何統計成一個人呢?
方法很簡單,在根目錄下增加一個 .mailmap 的檔案,裡面的內容是作者名稱及郵件的對應關係,如下:

黃浩杭	<[email protected]>
黃浩杭	<[email protected]>

再統計,就按配置的作者名稱顯示出來了:

48823 黃浩杭
# ...下面略

輸出統計耗時

上面統計的命令,可能執行的時間會比較長,所以可以把它放到一個指令碼檔案,然後新增執行許可權並把指令碼所在位置新增到 path 變數中,然後執行這個指令碼檔案,在後面加上 & 使它在後臺執行。
另外,我們可以加上耗時統計,獲取統計前後的秒數,計算它們之差得出耗時秒數。這裡獲取秒數,在 Ubuntu 和 Mac 上方法不同,最終指令碼如下:

Ubuntu 最終指令碼

#!/bin/bash

start=`date +%s.%N`

for file in `git ls-fles |grep -P "(\.xml)|(\.java)|(\.md)|(\.gradle)|(\.kt)"`; do git blame --line-porcelain $file |sed -n 's/^author //p'; done |sort |uniq -c |sort -rn

end=`date +%s.%N`
echo 統計共耗時`echo "$end - $start" |bc -l`

Mac 最終指令碼

#!/bin/bash

start=`date +%s.%S`

for file in `git ls-files |grep -e "\.xml" -e "\.java" -e "\.md" -e "\.gradle" -e "\.kt"`; do git blame --line-porcelain $file|sed -n 's/^author //p'; done |sort |uniq -c |sort -rn

end=`date +%s.%S`
echo 統計共耗時`echo "$end - $start" |bc -l`