一、Gerrit 是什么?为什么需要它?

Gerrit 是一款基于 Git 的开源代码审查工具,核心价值在于强制代码评审流程,通过多人协作把关代码质量,减少线上缺陷,同时保留完整的变更追溯记录。它特别适合中小型团队:

  • 支持细粒度权限控制(谁能提交 / 评审 / 合并代码)

  • 与 Git 原生兼容,无需改变现有开发习惯

  • 网页端可视化评审界面,支持评论、打分、变更追踪

  • 可集成 CI/CD 流程(如 Jenkins、GitHub Actions),实现自动化验证

对比直接提交 Git 仓库:Gerrit 通过「虚拟分支」机制拦截直接提交,确保所有代码变更都经过评审,尤其适合需要严格质量管控的 C/C++ 工程(如嵌入式、工具类项目)。

二、环境准备与安装配置(服务器端)

1. 核心依赖

  • 操作系统:Linux(推荐 Ubuntu 20.04+/CentOS 7+)

  • 依赖软件:Java 8+(Gerrit 基于 Java 开发)、Git、数据库(默认 H2,生产环境推荐 MySQL/PostgreSQL)

2. 安装步骤

1
2
3
4
5
6
7
8
9
10
11
# 1. 安装 Java 依赖
sudo apt update && sudo apt install openjdk-11-jdk -y

# 2. 创建 Gerrit 专用用户
sudo useradd -m gerrit && sudo su - gerrit

# 3. 下载 Gerrit 安装包(从官网获取最新版本,示例为 3.9.1)
wget https://gerrit-releases.storage.googleapis.com/gerrit-3.9.1.war

# 4. 初始化 Gerrit 站点(指定安装目录和管理员邮箱)
java -jar gerrit-3.9.1.war init -d review_site

3. 关键配置(review_site/etc/gerrit.config)

初始化后需调整核心配置项,确保服务可访问:

1
2
3
4
5
6
7
8
9
10
11
[gerrit]
basePath = git # Git 仓库存储路径
serverId = xxxxxxxx # 自动生成,无需修改
canonicalWebUrl = http://你的服务器IP:8080/ # 网页访问地址
[httpd]
listenUrl = http://*:8080/ # 监听端口(默认 8080)
[sshd]
listenAddress = *:29418 # SSH 端口(Git 交互用,默认 29418)
[database]
type = h2 # 开发环境用 H2,生产环境切换为 mysql
database = review_site/db/ReviewDB

4. 启动 / 停止 Gerrit 服务

1
2
3
4
5
# 启动服务
sudo /home/gerrit/review_site/bin/gerrit.sh start

# 停止服务
sudo /home/gerrit/review_site/bin/gerrit.sh stop

启动成功后,访问 http://服务器IP:8080 即可看到 Gerrit 登录界面。

三、客户端配置(开发者侧)

开发者需完成 SSH 密钥绑定、Git 仓库克隆和钩子配置,才能提交代码到 Gerrit。

1. 绑定 SSH 密钥(核心步骤)

Gerrit 通过 SSH 验证用户身份,需将本地公钥添加到 Gerrit 账户:

  1. 本地生成 SSH 密钥(若已存在可跳过):
1
ssh-keygen -t rsa -C "你的邮箱地址"  # 一路回车默认生成 ~/.ssh/id_rsa.pub
  1. 登录 Gerrit 网页端 → 点击右上角头像 → Settings → SSH Public Keys → 粘贴 id_rsa.pub 内容 → 保存。

2. 克隆 Gerrit 仓库

通过 Gerrit 提供的 SSH 地址克隆仓库(而非直接克隆原 Git 仓库):

1
2
3
# 格式:git clone ssh://用户名@服务器IP:29418/项目名
git clone ssh://user@192.168.1.100:29418/MyProject
cd MyProject

3. 配置 Commit-msg 钩子(自动生成 Change-ID)

Gerrit 要求每个提交都有唯一 Change-ID(用于追踪变更请求),需安装钩子脚本自动生成:

1
2
3
4
5
6
7
8
# 方法 1:通过 scp 从 Gerrit 服务器下载(推荐)
scp -P 29418 user@192.168.1.100:hooks/commit-msg .git/hooks/

# 方法 2:通过 curl 下载(服务器未开放 scp 时用)
curl http://192.168.1.100:8080/tools/hooks/commit-msg > .git/hooks/commit-msg

# 赋予执行权限(关键步骤,否则钩子不生效)
chmod u+x .git/hooks/commit-msg

4. 配置 Git 用户名 / 邮箱(与 Gerrit 账户一致)

1
2
git config --global user.name "你的 Gerrit 用户名"
git config --global user.email "你的 Gerrit 绑定邮箱"

四、核心工作流:提交代码 → 评审 → 合并

Gerrit 的核心流程是「推送变更请求 → 评审 → 合并」,开发者无需直接推送到主分支,而是推送到 Gerrit 的虚拟分支 refs/for/<目标分支>。

1. 完整操作步骤(命令行版)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. 切换到目标分支(如 main)
git checkout main && git pull origin main # 确保本地分支最新

# 2. 创建特性分支(开发新功能/修复bug用)
git checkout -b feature/login-fix

# 3. 编写代码后,提交本地变更(提交信息需清晰,便于评审)
git add .
git commit -m "fix: 修复登录流程的空指针异常
- 增加用户名非空校验
- 优化密码加密逻辑"
# 提交后,钩子会自动在提交信息末尾添加 Change-ID: Ixxxxxxx

# 4. 推送到 Gerrit 虚拟分支(关键命令)
# 格式:git push <远程名> <本地分支>:refs/for/<目标分支>
git push origin feature/login-fix:refs/for/main

2. 简化推送命令(配置 Git 别名)

每次输入长命令繁琐,可配置全局别名 push-for-review:

1
2
3
4
5
6
7
8
# 若远程名为 origin(默认克隆后的远程名)
git config --global alias.push-for-review "push origin head:refs/for/main"

# 后续推送直接用:
git push-for-review

# 若需推送到其他分支(如 dev),临时指定:
git push origin head:refs/for/dev

3. 分组提交(Topic 功能)

多个相关变更(如同一功能的多个提交)可通过 topic 分组,便于评审者批量处理:

1
git push origin head:refs/for/main%topic=login-optimize  # 分组名为 login-optimize

五、代码评审流程(评审者侧)

开发者推送变更后,评审者需在 Gerrit 网页端完成审核:

登录 Gerrit → 点击 Changes → 选择待评审的变更请求

核心操作:

    • 查看变更:点击 Files 查看代码差异,可在具体行号添加评论
    • 打分
      • -1:需要修改(存在问题)
      • +1:代码合格(可合并,但需管理员最终批准)
      • -2:强烈反对(重大问题,禁止合并)
      • +2:批准合并(仅管理员 / 资深开发者有此权限)
    • 提交合并:当变更获得 +2 评分且无 -1/-2 时,点击 Submit 合并到目标分支

4. 开发者处理评审意见

若评审者提出修改意见,需在本地分支修改后重新提交:

1
2
3
4
5
# 1. 基于原特性分支修改代码
git add .
git commit --amend # 追加修改(保留原 Change-ID,避免创建新变更)
# 2. 重新推送到 Gerrit(自动覆盖原变更请求)
git push-for-review

六、CMake 工程集成 Gerrit(关键适配)

对于 C/C++ 工程(尤其是用 CMake 构建的项目),需注意 2 个核心适配点,确保评审流程不影响构建:

1. 忽略构建产物(.gitignore)

避免将 CMake 构建目录、可执行文件推送到 Gerrit,在项目根目录创建 .gitignore:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# CMake 构建产物
build/
cmake-build-*/
generated/ # 对应前文版本管理的 generated/version.h 目录

# 可执行文件
*.exe
*.out
*.so
*.dll

# 其他中间文件
.DS_Store
.vscode/

2. 版本号与 Gerrit 变更协同

前文提到的「基于 Git 提交数的版本管理」方案,可与 Gerrit 无缝兼容:

  • Gerrit 合并变更后,Git 仓库会新增一个提交(包含评审后的代码)

  • CMake 脚本自动统计提交数,生成补丁版本号(如 2.1.20,20 为合并后的总提交数)

  • 无需修改 version.cmake,版本号会随 Gerrit 合并自动更新

七、常见问题与避坑指南

1. 推送失败:fatal: Could not read from remote repository

  • 原因:SSH 密钥未绑定,或端口错误(Gerrit SSH 端口是 29418,而非默认 22)

  • 解决:重新检查 SSH 密钥配置,确保克隆命令中的端口是 29418。

2. 提交无 Change-ID:推送后 Gerrit 看不到变更

  • 原因:Commit-msg 钩子未安装或无执行权限

  • 解决:重新执行钩子配置命令,确保 chmod u+x .git/hooks/commit-msg 生效,可通过 git log 查看提交信息是否有 Change-ID 行。

3. CI 集成时 Git 提交数统计错误

  • 原因:CI 克隆仓库时默认 fetch-depth: 1,仅获取最新提交,导致提交数统计不全

  • 解决:在 CI 配置中设置 fetch-depth: 0(如 GitHub Actions),完整克隆仓库历史(参考前文 CMake 集成的 CI 配置)。

4. 权限不足:无法提交 / 合并变更

  • 原因:管理员未分配对应权限(如 Submit 权限)

  • 解决:联系 Gerrit 管理员 → 网页端 Projects → 选择项目 → Access → 为你的用户组添加 Submit 或 Code-Review 权限。

八、总结

Gerrit 作为一款轻量级代码审查工具,核心优势是「无侵入式集成 Git 工作流」和「细粒度权限控制」,特别适合需要严格质量管控的 C/C++ 工程。

对于使用 CMake 的团队,只需完成「客户端钩子配置 + .gitignore 优化」,即可将 Gerrit 无缝融入现有开发流程,同时与前文的「Git 提交数版本管理」方案互补:Gerrit 保障代码质量,CMake 自动管理版本号,形成「质量管控 + 版本追溯」的完整闭环。