无SSH权限且API受限,如何批量获取Gerrit已关闭评审?
通过Git获取Gerrit已关闭评审的可行方案
我之前也碰到过类似的Gerrit数据收集困境——REST API有查询限制还慢,Perceval又要SSH权限拿不到,后来摸索出用Git直接获取的方法,亲测适合无SSH权限的场景,分享给你:
核心原理
Gerrit会把所有变更(包括已关闭的MERGED/ABANDONED状态)以特殊格式的Git引用(refs)存储在仓库中,格式为refs/changes/xx/yyyy/zz:
xx是变更ID的最后两位yyyy是完整的变更IDzz是该变更的补丁集版本
只要你有仓库的HTTP/HTTPS只读权限,就能拉取这些refs并解析出评审状态。
具体步骤
1. 克隆目标Gerrit仓库
先把Gerrit对应的主仓库克隆到本地(注意要是Gerrit托管的原仓库,不是个人fork的):
git clone <Gerrit仓库的HTTP/HTTPS地址> cd <仓库目录>
2. 拉取所有变更引用
默认克隆不会同步这些特殊的变更refs,需要手动执行fetch命令:
git fetch origin 'refs/changes/*:refs/changes/*'
这个命令会把远程所有refs/changes/开头的引用完整拉到本地。如果仓库很大,也可以分批拉取(比如按refs/changes/00/*到refs/changes/ff/*分256批),减少单次请求的压力。
3. 批量解析已关闭评审
每个变更的补丁集提交信息里,Gerrit会嵌入评审元数据(比如Change-Id和Status)。我们可以写脚本批量提取并过滤已关闭的变更:
Shell脚本示例
# 创建结果文件 touch closed_changes.txt # 遍历所有变更refs,去重提取已关闭变更 declare -A seen_change_ids for ref in $(git for-each-ref --format='%(refname)' refs/changes/*); do # 获取提交信息 commit_msg=$(git show --format=%B -s $ref) # 提取Change-Id和状态 change_id=$(echo "$commit_msg" | grep -oP 'Change-Id:\s+\K.*') status=$(echo "$commit_msg" | grep -oP 'Status:\s+\K.*') # 跳过无状态或已处理过的Change-Id if [[ -z "$status" || -n "${seen_change_ids[$change_id]}" ]]; then continue fi # 只保留已关闭状态(MERGED/ABANDONED) if [[ "$status" == "MERGED" || "$status" == "ABANDONED" ]]; then seen_change_ids[$change_id]=1 echo "Change-Id: $change_id | Status: $status | Latest Patch Ref: $ref" >> closed_changes.txt fi done echo "已完成,结果已写入closed_changes.txt"
特殊情况处理
如果你的Gerrit版本较旧,提交信息里没有Status字段,可以结合REST API做补充:拿到Change-Id后,调用GET /changes/<Change-Id>接口单独查询状态——因为是单个查询,不会触发批量限制,速度也能接受。
优化建议
- 拉取refs时可以加
--depth 1参数,只拉取最新的补丁集提交,减少本地存储占用。 - 脚本可以根据需求扩展,比如提取评审时间、提交者信息等,这些都能从提交信息或Git日志中拿到。
内容的提问来源于stack exchange,提问作者Michael Dorner
相关产品推荐
相关产品推荐

