【Gerrit Patch】批量下载 Gerrit 提交的 Patch

【Gerrit Patch】批量下载 Gerrit 提交的 Patch

  • [一、ssh 方案](#一、ssh 方案)
    • [1.1 查看 Gerrit 的服务器地址和端口](#1.1 查看 Gerrit 的服务器地址和端口)
    • [1.2 gerrit query 命令查询](#1.2 gerrit query 命令查询)
  • [二、curl 方案](#二、curl 方案)
    • [2.1 Gerrit REST API 介绍](#2.1 Gerrit REST API 介绍)
    • [2.2 Gerrit REST API 使用](#2.2 Gerrit REST API 使用)
  • [三、shell 脚本批处理](#三、shell 脚本批处理)

一、ssh 方案

1.1 查看 Gerrit 的服务器地址和端口

查看远程仓库URL

最直接的方法是查看本地Git仓库中配置的远程仓库地址:

bash 复制代码
git remote -v

这条命令会列出所有已配置的远程仓库及其对应的URL。Gerrit服务器的IP和端口通常包含在远程仓库的URL中,格式一般为 ssh://username@ip:port/path/to/repo.git

检查Git配置文件

如果通过 git remote -v获取的信息不够详细,可以直接查看Git配置文件:

bash 复制代码
cat .git/config

这个文件包含了当前仓库的所有配置信息,其中 [remote "origin"]或类似的段落会明确显示远程Gerrit服务器的完整URL。

验证SSH连接配置

对于使用SSH协议的Gerrit仓库,还可以检查SSH配置文件中是否定义了Gerrit服务器的别名和连接参数:

bash 复制代码
cat ~/.ssh/config

如果之前配置过Gerrit连接,这里可能会有类似以下的条目:

bash 复制代码
Host my-gerrit
    HostName 192.168.1.100
    Port 29418
    User your-username

获取 ssh_info

已经 Gerrit 网址 192.168.1.100,使用 curl

bash 复制代码
$ curl http://192.168.1.100:8080/ssh_info
192.168.1.100 29418

1.2 gerrit query 命令查询

知道主机名和端口后就可以要验证您的 SSH 密钥是否正常工作,默认情况下,Gerrit 在 端口 29418,使用与 Web 服务器相同的主机名:

bash 复制代码
$ ssh -p 29418 fangjian@192.168.1.100

  ****    Welcome to Gerrit Code Review    ****

  Hi fangjian, you have successfully connected over SSH.

  Unfortunately, interactive shells are disabled.
  To clone a hosted Git repository, use:

  git clone ssh://fangjian@192.168..1.100:29418/REPOSITORY_NAME.git

Connection to 192.168.0.166 closed.

输入以上日志就说明 SSH 连接成功!

参考文档:Gerrit Code Review - SSH - Command Line Tools

gerrit queryhttps://gerrit-documentation.storage.googleapis.com/Documentation/2.13.7/cmd-query.html

gerrit query - 查询使用方式

bash 复制代码
ssh -p <port> <host> gerrit query
  [--format {TEXT | JSON}]
  [--current-patch-set]
  [--patch-sets | --all-approvals]
  [--files]
  [--comments]
  [--commit-message]
  [--dependencies]
  [--submit-records]
  [--all-reviewers]
  [--start <n> | -S <n>]
  [--]
  <query>
  [limit:<n>]

使用示例

bash 复制代码
$ ssh -p 29418 review.example.com gerrit query --format=JSON --start 42 status:open 
bash 复制代码
# 查看change id: 230d069
ssh -p 29419 fangjian@10.20.40.21 gerrit query --current-patch-set --format=TEXT 230d069

# 获取所有 change id
ssh -p 29419 fangjian@10.20.40.21 gerrit query --format=TEXT owner:fangjian is:open
ssh -p 29419 fangjian@10.20.40.21 gerrit query owner:fangjian --current-patch-set --format=TEXT > changes.txt

# 分页查询
ssh -p 29419 fangjian@10.20.40.21 gerrit query --format=JSON owner:fangjian is:open --current-patch-set --commit-message --start 500 limit:500

由于 gerrit ssh 命令行没有提供下载 patch 的方法,我们只能使用 gerrit query 来查询提交的信息,如 change id

二、curl 方案

2.1 Gerrit REST API 介绍

参考文档:Gerrit Code Review - REST API

Query Changeshttps://gerrit-documentation.storage.googleapis.com/Documentation/2.13.7/rest-api-changes.html#list-changes

获取一个修订版的格式化补丁:

bash 复制代码
GET /changes/{change-id}/revisions/{revision-id}/patch

Get Patchhttps://gerrit-documentation.storage.googleapis.com/Documentation/2.13.7/rest-api-changes.html#get-patch

查询更改,通过提供查询字符串 参数:

bash 复制代码
GET /changes/

还有其他功能的 API,这里我们只需要使用这2个即可,一个用于有条件的获取 change id,另一个用于根据 change id 下载 patch。

2.2 Gerrit REST API 使用

访问 Gerrit 的 REST API(而不是使用 Basic Auth),你需要先获取有效的 Gerrit 登录 Cookie 或者 有效的用户名和密码 ,并将其附加到 curl请求中。

通过 --cookiecookie 方式

bash 复制代码
curl --cookie "GerritAccount=aQEfprrnWN9qOAL5rYA391uF.T0AGSWuRW" "http://192.168.0.166:8080/changes/?q=owner:fangjian+status:merged"

通过 -u用户名:密码方式

bash 复制代码
curl -u "fangjian:xxxx" "http://192.168.0.166:8080/changes/?q=owner:fangjian+status:merged"

使用示例

bash 复制代码
# 获取所有change id
curl -u "fangjian:Droi*#2036" "http://10.20.40.21:8088/a/changes/?q=owner:fangjian+status:open"

# 分页获取
curl -u "fangjian:Droi*#2036" "http://10.20.40.21:8088/a/changes/?q=owner:fangjian+status:open&n=500&start=0"

# 下载指定change id 的patch file
curl -u "fangjian:xxxx" "http://10.20.40.21:8088/a/changes/22141/revisions/current/patch" | base64 -d > my_patch.patch

三、shell 脚本批处理

bash 复制代码
#!/bin/bash

# Gerrit 登录信息
GERRIT_HOST="http://10.20.40.21:8088"   # Gerrit REST API Host
USERNAME="fangjian"                        # Gerrit 用户名
PASSWORD="xxxx"                        # Gerrit 密码

# 输入参数
TARGET_OWNER="fangjian"                      # 查询的目标用户
OUTPUT_DIR="./gerrit_patch"                   # 本地保存 Patch 文件的目录
LIMIT=500                                    # 每次查询的记录条数上限

# 创建保存 Patch 文件的目录
mkdir -p "${OUTPUT_DIR}"

# 初始化分页参数
START=0                                      # 从 0 偏移,分页获取数据
HAS_MORE_CHANGES=true                        # 初始化为有更多的变更记录

echo "Fetching changes for owner: ${TARGET_OWNER}..."

# 循环查询直到所有变更记录处理完成
while [ "${HAS_MORE_CHANGES}" = true ]; do
    echo "Fetching changes starting from offset: ${START}"

    # 调用 Gerrit REST API 获取 Change 列表(分页)
    RESPONSE=$(curl -s -u "${USERNAME}:${PASSWORD}" \
      "${GERRIT_HOST}/changes/?q=owner:${TARGET_OWNER}&n=${LIMIT}&start=${START}" \
      -H "Content-Type: application/json")

    # 检查 API 调用是否成功
    if [ -z "${RESPONSE}" ]; then
        echo "Error: Failed to fetch changes from Gerrit. Exiting..."
        exit 1
    fi

    # 去掉 Gerrit 特有的前缀 )]}'
    CLEANED_RESPONSE=$(echo "${RESPONSE}" | sed 's/)]}\x27//')

    # 检查是否有数据返回
    if [ -z "${CLEANED_RESPONSE}" ] || [[ "${CLEANED_RESPONSE}" == "[]" ]]; then
        echo "No changes found. Exiting..."
        break
    fi

    # 解析返回的 JSON 数据,提取必要字段,逐个处理 Change
    echo "${CLEANED_RESPONSE}" | jq -c '.[]' | while read -r CHANGE; do
        # 提取 Change 的基本信息
        CHANGE_ID=$(echo "${CHANGE}" | jq -r '.id')                     # Change ID
        SUBJECT=$(echo "${CHANGE}" | jq -r '.subject')                 # 变更内容的标题
        CREATED=$(echo "${CHANGE}" | jq -r '.created' | awk '{print $1}') # 仅保留日期部分,比如2025-02-24
        PROJECT=$(echo "${CHANGE}" | jq -r '.project')                 # 项目名称
        BRANCH=$(echo "${CHANGE}" | jq -r '.branch')                   # 分支名称

        # 对 PROJECT 提取最后一级关键字,如 "documents"
        PROJECT_KEY=$(echo "${PROJECT}" | awk -F'/' '{print $NF}')

        # 构造安全的文件名规则
        SAFE_PROJECT=$(echo "${PROJECT_KEY}" | tr '/:' '-')               # 替换 `/` 和非法字符为 `-`
        SAFE_BRANCH=$(echo "${BRANCH}" | tr '/:' '-')                     # 替换 `/` 和非法字符为 `-`
        
        # 特殊字符处理:SUBJECT 允许中文和其他字符,替换非法文件名字符
        SAFE_SUBJECT=$(echo "${SUBJECT}" | tr '/\\:*?"<>|&' '_')          

        # 将创建的 PATCH 文件名标准化
        PATCH_FILENAME="${SAFE_PROJECT}-${SAFE_BRANCH}-${CREATED}-${SAFE_SUBJECT}.patch"

        echo "Downloading patch for Change-ID: ${CHANGE_ID} -> ${PATCH_FILENAME}"

        # 下载 Patch 文件
        curl -s -u "${USERNAME}:${PASSWORD}" \
          "${GERRIT_HOST}/changes/${CHANGE_ID}/revisions/current/patch" | base64 -d > "${OUTPUT_DIR}/${PATCH_FILENAME}"

        # 检查下载是否成功
        if [ $? -eq 0 ]; then
            echo "Saved patch file: ${OUTPUT_DIR}/${PATCH_FILENAME}"
        else
            echo "Failed to download patch for Change-ID: ${CHANGE_ID}"
        fi
    done

    # 判断是否还有更多的记录 (通过 REST API `_more_changes` 字段)
    if echo "${CLEANED_RESPONSE}" | grep -q '"_more_changes":true'; then
        HAS_MORE_CHANGES=true
        START=$((START + LIMIT)) # 增加偏移量,获取下一批记录
    else
        HAS_MORE_CHANGES=false
        echo "All changes processed."
    fi
done

echo "All patches have been downloaded to: ${OUTPUT_DIR}"
相关推荐
T - mars15 小时前
Pycharm中使用git
ide·git·pycharm
jason_yang17 小时前
Workspace搭建Vue3+组件分离的Monorepo项目
git·npm·前端工程化
鸽鸽程序猿21 小时前
【Git】Git 简介及基本操作
git
ziyue75751 天前
idea终端添加git-bash,支持linux的shell语法
linux·git·bash·idea·软件
风也温柔☆1 天前
idea 拉取分支git pull报错 The branch to pull from should be selected
git·intellij-idea·debug·git pull
博闻善行2 天前
git基础操作
运维·git
黑面前端小书生2 天前
Git 下载 、安装、规范
git
Rhys..2 天前
Git & GitHub 个人账户创建教程
git·github
wuyunhang1234562 天前
Git----常用指令入门
git