git提供了强大的功能,可以对仓库信息和历史一览无余,但是git命令的使用相对比较繁琐,而且很多时候需要借助其他shell工具组成栈来联合一起完成信息查询,这对不是很熟悉shell命令行的人是一项比较艰难的任务。那么有什么简单的方法可以完成这个任务呢?
相对比很多IT小伙伴可能都比较熟悉SQL语言,一种比较通用便捷的数据库查询和操作语言。本文虫虫就给大家介绍一个开源工具Askgit,用来在git存储库执行SQL查询的命令行工具。在通过公共接口(SQL)临时查询磁盘上的git存储库,来代替各种繁琐git命令行。
安装
Askgit可以可以使用以下方法构建go 命令直接安装二进制文件:
go get -v -tags=sqlite_vtable github.com/augmentable-dev/askgit
个命令将会下载软件包,相关性类库,并将所有内容编译为可执行文件。如果无法确定它的安装位置,请检查是否已GOPATH正确设置,然后它将以结尾$GOPATH/bin。
另外我们可以通过指定$GOPATH方式将其安装到特定的目录(比如当前目录):
GOBIN=$(pwd) go get -v -tags=sqlite_vtable github.com/augmentable-dev/askgit
Askgit也支持通过docker方式安装:
docker pull augmentable/askgit:latest
docker方式安装的使用方法如下:
docker run -v `pwd`:/repo:ro askgit "SELECT * FROM commits"
基本使用
获取测试库
本文以Askgit的github仓库为例进行,先clone一个源码。注意对于一些比较大的git仓库,Askgit操作比较慢慢,这可能是目前发现一个问题。
commit信息
Git的基本单位是commit,commit表示对仓库文件的变更历史。通过对commit的信息可以追溯参考每一个文件延续历史信息。
commit表中各个字段信息如:
字段 类型 说明
id TEXT commitID
message TEXT 提交注释
summary TEXT
author_name TEXT 作者
author_email TEXT作者邮箱
author_when DATETIME作者时间
committer_name TEXT 提交者
committer_email TEXT提交者邮箱
committer_when DATETIME提交时间
parent_id TEXT 父commitID
parent_count INT 父commit计数
tree_id TEXT 数对象ID
additions INT 增加
deletions INT 删除
repo仓库的历史时间
首先我们来仓库的最早提交信息时间。对于大多数仓库,日期将是相似的,使用author_when则代码是编写时(根据作者)。对于一些历史项目,可能他们是通过电子邮件发布补丁(例如linux或postgres),是通过committer_when是添加代码时的时间。
第一次提交信息
我们可以搜索第一次提交时候的相关信息,包括提交人,commit信息,邮箱地址,提交时间等:
askgit "select message, author_name, author_email, author_when from commits order by committer_when asc limit 1"
显示askgit仓库第一次提交到时候是2020年7月3日,由Patrick DeVivo提交的,项目实际一个非常新的项目。
Top 10提交者
提交添加的代码最多的10个作者是:
askgit "select summary, author_name, author_when, additions from commits order by additions desc limit 10"
可以看到,项目主要开发者有Patrick DeVivo和vialenon 两个都是由他们两个提交的。
贡献率图
askgit "WITH total_commits(total) AS (SELECT count(*) AS total FROM commits)SELECTauthor_name,round(count(*)*100.0 / (SELECT total FROM total_commits), 2) AS percentage,printf('%.' || (CAST (round(count(*)*100.0 / (SELECT total FROM total_commits)) AS INT) + 1) || 'c', '█') AS commitsFROM commits GROUP BY author_nameORDER BY percentage DESC"
Top 10代码清理着
删除代码最多的10个人:
askgit "select summary, author_name, author_when, deletions from commits order by deletions desc limit 10"
同样,项目代码清理也有Patrick DeVivo和vialenon 两个。
总提交次数
askgit "select count(*) from commits"
+----------+
| COUNT(*) |
+----------+
| 79 |
+----------+
提交次数只有79次。
最频繁的提交者
按提交者分组author_name并按提交者排序。
askgit "select count(*) as count, author_name from commits group by author_name having count > 1 order by count desc"
按月提交统计
可以使用sqlite日期函数查看项目随时间的活动。可以看到,一开始有很多活动,并且活动逐渐减少。
askgit "select strftime(\"%Y-%m\", author_when) as 'month',count(*) as total_commits, sum(additions), sum(deletions)from commits group by strftime(\"%Y-%me\", author_when) order by strftime(\"%Y-%m\", author_when);"
项目才两个月,上个月提交了71次,增加了4584行代码,删除了1315行代码。这个月只有一次,增加和删除的代码分别为254和136。
作者提交日历表
askgit "SELECTcount(*) AS commits,count(CASE WHEN strftime('%w',author_when)='0' THEN 1 END) AS sunday,count(CASE WHEN strftime('%w',author_when)='1' THEN 1 END) AS monday,count(CASE WHEN strftime('%w',author_when)='2' THEN 1 END) AS tuesday,count(CASE WHEN strftime('%w',author_when)='3' THEN 1 END) AS wednesday,count(CASE WHEN strftime('%w',author_when)='4' THEN 1 END) AS thursday,count(CASE WHEN strftime('%w',author_when)='5' THEN 1 END) AS friday,count(CASE WHEN strftime('%w',author_when)='6' THEN 1 END) AS saturday,author_emailFROM commits GROUP BY author_email ORDER BY commits"
标签
标签在git中可以很大程度上表示版本的发布,更具标签信息可以查看项目发版情况。
获取标签列表
在这里,可以看到该项目的标签列表。
askgit "select name, tagger_name, target_type from tags"
如果target_type是NULL这意味着它是一个轻量级的标签,并没有提交与它相关联。大多数情况下,人们会进行提交,并且由于提交具有日期,因此可以更轻松地进行关联。
标签的创建者和时间
下面的sql语句可以找出谁创建了标签以及对应的消息是什么。
askgit "select name, commits.id, commits.message, author_name, author_email, author_when from tags, commits where tags.target_type = commits.id order by author_when"
找出开始和结束日期
可以根据创建标签的时间戳询问以上所有问题。这将使我们对这段时间内项目的进展情况有所了解。让我们创建一个简单的CSV文件,以便更轻松地提出这些问题。
askgit "select name, commits.id, author_when from tags, commits where tags.target_type = commits.id order by author_when" --format csv > tags.csv
下面脚本为每个标签都有开始时间和结束时间。以初始提交作为开始时间,然后使用之前的标记。
PREV_DATE=$(askgit "select min(author_when) as first from commits" --format csv |grep -v first)while IFS=, read -r tag id date; doif [[ "$tag" != "name" ]]; thenecho ${tag},${id},${PREV_DATE},${date}PREV_DATE=${date}fidone < tags.csv >tag-timess.csv
标签统计
通过遍历该文件,并为每个标记提取一些统计信息。
while IFS=, read -r tag id start end; doecho $tagaskgit "select count(*) as count from commits where author_when > '${start}' and author_when askgit "select count(*) as count, author_name from commits where author_when > '${start}' and author_when done < tag-timess.csv
文件
askgit中有一个file表,该表显示了特定提交时的存储库状态,因此对于实际跟踪在提交中或两次提交之间发生的更改没有太大用处。最好使用git diff-tree和git log查找相关的信息。
使用特定提交修改的文件
可以看到在最新提交中更改了哪些文件:
git diff-tree --no-commit-id -r --name-only HEAD^1
标签修改的文件
我们可以使用..指定提交范围的方式,因此让我们看一下在v1.5.0和之间哪些文件已更改v1.7.0。
git diff-tree --no-commit-id -r --name-only v1.5.0..v1.7.0
文件历史
查看文件是何时添加的很有用。同样,这时候用askgit会很慢,最好是用git log要快很多。
本例中,显示特定文件cmd/root.go历史记录。通过--reverse将传递一些格式选项,以便对git log进行格式化解析
git log --reverse --pretty='format:%aI %h %an %s' cmd/root.go
--reverse格式选项说明如下
%aI 提交日期
%an 提交者
%h 为的短commitID
%s 提交的信息字
总结
本文我们介绍一个新git工具Askgit,该工具使用Golang开发,通过解析git对象数据库,实现SQL查询接口对git相关信息进行查询,该工具对熟悉sql并要求对git项目分析的人提供了一个便捷的方法。但是工具目前应用于大型项目时对比git原生命令明显很慢,性能较差,需要更进一步提高性能。
领取专属 10元无门槛券
私享最新 技术干货