计算 git 存储库中每位作者的代码行数

Counting lines of code per author in a git repository

所以我和其他几个程序员在一个团队中,需要在我们的 git 存储库中获取每个作者的代码行数。这不仅仅意味着作者修改的行,因为那将包括空白行和注释行。理想情况下,我可以创建一个仅包含特定作者的提交的新分支(--author="BtheDestroyer" 我自己),然后使用 cloc 分别获取评论行数和代码行数。我试过使用

git log --author="BtheDestroyer" --format=%H > mycommits
git checkout --orphan mycommits
tac mycommits| while read sha; do git cherry-pick --no-commit ${sha}; done

然而,在最后一行中,我收到了大量以下错误:

filepath: unmerged (commit-id-1)
filepath: unmerged (commit-id-2)
error: your index file is unmerged.
fatal: cherry-pick failed

我也不确定这是否会通过过程中的其他提交结束快进。有什么想法吗?

回答我自己的问题:

我最终使用 git blame 和 Bourne shell 脚本循环遍历源文件夹中的不同文件,使用 grepcut 将它们转换回代码,将输出组织到临时文件中,然后 运行 cloc 就可以了。

这是我的 shell 脚本,供任何想做类似事情的人使用(我在 ./Blame/ 中有它,所以适当地更改 SOURCE!):

#!/bin/bash
#Name of user to check
#  If you have multiple usernames, separate them with a space
#  The full name is not required, just enough to not be ambiguous
USERS="YOUR USERNAMES HERE"
#Directories
SOURCE=../source

for USER in $USERS
do
    #clear blame files
    echo "" > $USER-Blame.h
    echo "" > $USER-Blame.cpp
    echo "" > $USER-Blame.sh
    echo "Finding blame for $USER..."
    #C++ files
    echo "  Finding blame for C++ files..."
    for f in $SOURCE/*.cpp
    do
        git blame "$f" | grep "$USER" | cut -c 70- >> "$USER-Blame.cpp"
    done
    #Header files
    echo "  Finding blame for Header files..."
    for f in $SOURCE/*.h
    do
        git blame "$f" | grep "$USER" | cut -c 70- >> "$USER-Blame.h"
    done
    #Shell script files
    echo "  Finding blame for shell script files..."
    for f in ./GetUSERBlame.sh
    do
        git blame "$f" | grep "$USER" | cut -c 70- >> "$USER-Blame.sh"
    done
done

for USER in $USERS
do
#cloc
echo "Blame for all users found! Cloc-ing $USER..."
cloc $USER-Blame.* --quiet
#this line is for cleaning up the temporary files
#if you want to save them for future reference, comment this out.
rm $USER-Blame.* -f
done

这是我的单线:

function gitfilecontributors() { local perfile="false" ; if [[  = "-f" ]]; then perfile="true" ; shift ; fi ; if [[ $# -eq 0 ]]; then echo "no files given!" >&2 ; return 1 ; else local f ; { for f in "$@"; do echo "$f" ; git blame --show-email "$f" | sed -nE 's/^[^ ]* *.<([^>]*)>.*$/: /p' | sort | uniq -c | sort -r -nk1 ; done } | if [[ "$perfile" = "true" ]]; then tee /tmp/gitblamestats.txt ; else tee /tmp/gitblamestats.txt >/dev/null ; fi ; echo ; echo "total:" ; awk -v FS=' *: *' '/^ *[0-9]/{sums[] += } END { for (i in sums) printf("%7s : %s\n", sums[i], i)}' /tmp/gitblamestats.txt | sort -r -nk1 ; fi ; }

或换行符:

gitfilecontributors ()
{
    local perfile="false";
    if [[  = "-f" ]]; then
        perfile="true";
        shift;
    fi;
    if [[ $# -eq 0 ]]; then
        echo "no files given!" 1>&2;
        return 1;
    else
        local f;
        {
            for f in "$@";
            do
                echo "$f";
                git blame --show-email "$f" | sed -nE 's/^[^ ]* *.<([^>]*)>.*$/: /p' | sort | uniq -c | sort -r -nk1;
            done
        } | if [[ "$perfile" = "true" ]]; then
            tee /tmp/gitblamestats.txt;
        else
            tee /tmp/gitblamestats.txt > /dev/null;
        fi;
        echo;
        echo "total:";
        awk -v FS=' *: *' '/^ *[0-9]/{sums[] += } END { for (i in sums) printf("%7s : %s\n", sums[i], i)}' /tmp/gitblamestats.txt | sort -r -nk1;
    fi
}

可使用您选择的四个文件夹。

选项 -f 显示每个文件,否则仅显示总数:

$ gitfilecontributors    $(fd --type f '.*' source)
total:
    139 : somebody@somewhere.de
     29 : else.user@somewhere.de
      9 : just.another@somewhere.de
gitfilecontributors -f $(fd --type f '.*' source)
source/040_InitialSetup.md
     80 : somebody@somewhere.de
     29 : else.user@somewhere.de
      6 : just.another@somewhere.de
README.md
     59 : somebody@somewhere.de
      5 : whosthat@somewhere.de
      3 : just.another@somewhere.de

total:
    139 : somebody@somewhere.de
     29 : else.user@somewhere.de
      9 : just.another@somewhere.de
      5 : whosthat@somewhere.de