You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无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是完整的变更ID
  • zz是该变更的补丁集版本

只要你有仓库的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:01:54