July 20, 2019

git统计工具轮子

最近弄了一个轮子,是用来统计 git 代码行数还有文件数目的一些占比,把这部分数据可视化到图表。仓库链接

背景

在造这个轮子之前,曾经在 gitlab 上面看到一部分统计的数据,发现只是统计了 commit 的提交数量、文件占比的比例;对于代码行数的纬度统计比较少。因此基本的需求就出来了。

研发思路

  1. 分析脚本:统计仓库的代码行数,分析所有文件的提交数据与文件类型
  2. 呈现静态页面:可视化分析脚本的数据
  3. 发布 npm 包:方便用于命令行执行生成分析数据

分析脚本

因为需要分析到每个文件行数的修改细节,因此这一部分一定需要 git 相关命令进行统计,目的是统计文件的每一个用户的提交行数;面向谷歌编程的我,找到以下命令:

1
2
3
4
$ git ls-files ${fileName} | while read f; do git blame --line-porcelain $f | grep '^author '; done | sort -f | uniq -ic | sort -n

# 将 ${fileName} 替换为 README.md
$ git ls-files README.md | while read f; do git blame --line-porcelain $f | grep '^author '; done | sort -f | uniq -ic | sort -n

输出结果:

1
2
10 author Not Committed Yet # 表示当前文件有10行还没有提交。Not Committed Yet 表示没有 commit 到仓库  
43 author jingzhiMo # 表示这个文件有43行是作者 jingzhiMo 提交的

然后需要对仓库的所有文件进行遍历,这里选择了深度优先遍历来处理,把最底部的文件节点不断往上统计;这样可以统计到每个文件夹的详细信息。

深度遍历

通常项目文件会有部分外部依赖文件或者部分不在 git 的跟踪下,这部分文件就不需要统计;最开始的思路是想通过项目的.gitignore判断文件是否在 git 跟踪下,不在就不进行统计,但是这个方法需要遍历.gitignore的规则,可能会判断出错。如果直接通过git判断就可以保证万无一失,利用git ls-files命令:

1
$ git ls-files no-track-file.js # 命令行输出为空

除此之外,默认会去除lock文件与一些图片媒体文件,例如: package-lock.jsonyarn.lock等。

静态页面呈现

呈现数据主要使用的工具是 echarts;本地开发使用create-react-app来搭建基础开发环境;左侧文件夹显示使用树状组件呈现,找了一圈找不到大概适合的,于是自己写一个简单的树状组件。树状组件大体思路是利用递归组件实现,组件内部包含自己组件:

1
2
3
4
5
6
7
8
9
 <!-- <Tree> 组件对应的渲染元素 -->
<div>
  <!-- 当前节点名称 -->
  <span>file name or folder name</span>
  <!-- children 当前文件夹对应的子文件夹-->
  <Tree data={children} />
  <!-- leaf 当前文件夹对应的文件-->
  <Tree data={leaf} />
</div>

每个节点都需要渲染自己的节点名称与直接子文件与直接文件夹;然后把对应子节点的数据继续传递到Tree组件,做到逐层数据展开,增强复用性。

发布 npm 包

为了节俭用户运行命令的时间与运行复杂度,所以把静态资源构建那一步需要在本地执行,生成好build的文件夹;但是因为生成的分析文件是动态生成的,所以暂时的处理方式是固定动态引入的文件名称,通过脚本生成的文件覆盖原有资源文件:

1
2
3
4
5
6
7
8
<!-- html入口文件 -->

<!DOCTYPE html>
<html>
  <head>
    <script src="source.js"></script>
  </head>
</html>
1
2
3
4
// source.js 运行文件调用该变量
window._source = {
  // ...
}

由于build文件夹是不需要git跟踪,而需要上传到npm包,因此需要.npmignore.gitignore配合使用才可以。

简单使用方法

  • 使用 npx 命令生成
1
2
3
$ cd git-repository /* 进入需要统计的 git 仓库文件夹 */
$ npx visualize-commit
$ cd commit-analyze /* 打开文件夹的 index.html 文件即可 */
  • 安装包到对应仓库
1
2
3
4
$ cd git-repository
$ npm install visualize-commit --save-dev
# or
$ yarn add visualize-commit --dev

package.json加入对应的脚本:

1
2
3
4
5
{
  "scripts": {
    "vsz": "vsz-commit"
  }
}

执行命令:

1
2
3
4
$ npm run vsz
# or
$ yarn add vsz
$ cd commit-analyze /* 打开文件夹的 index.html 文件即可 */

展望

现在这个代码统计功能还比较简单,希望看到文章的小伙伴可以提issue,使得统计的纬度更加多样化。现在给到自己将要做的功能可能有以下这些:

    • 统计多个版本的记录,查看不同版本代码行数的变化
    • 统计不同版本用户的提交情况
    • 统计不同用户 commit 数量的变化(与github统计commit相似)
    • 提供配置参数,例如生成文件夹的名称,统计/忽略统计的文件类型,过滤规则自定义
    • 统计代码量前X排序的模块