Gerrit集成Gitweb完整指南:代码审查与仓库浏览一键打通

发布时间:2026/10/8 18:17:59
Gerrit集成Gitweb完整指南:代码审查与仓库浏览一键打通
Gerrit 的代码审查流程在业界是出了名的严谨但真要论逛代码的体验它其实有点偏科——项目里的文件树就是一个最朴素的列表想看分支对比、翻历史、找 blame、查 tag全靠人肉在终端里敲命令。Gitweb 恰好就是来补这块短板的把两者接起来之后Gerrit 的项目页、变更页、提交列表上都会多出一个跳转链接点过去就是 Gitweb 那个清爽的仓库浏览界面。这篇文章记录的就是一次完整的 gerrit 配置过程——从安装 Gitweb、配 Apache、打通仓库读取权限到最后在 gerrit.config 里写 [gitweb] 段并验证生效顺手把踩过的坑也一起整理出来。如果你正在自建 Gerrit或者想把团队的代码浏览入口统一起来这篇可以直接照着抄。1. 为什么非要把 Gitweb 集成进 Gerrit1.1 Gerrit 的短板能审代码但不方便逛代码Gerrit 的核心定位是代码审查它把提交-评审-合入这条链路做得极其扎实但代价就是它对仓库本身的浏览能力非常克制。你在 Gerrit 的 Web 界面里可以看 diff、评 comment、追踪 review 状态可一旦想看某个分支的整体结构、某次提交改了哪些文件之外的内容、两个 tag 之间差了多少提交就只能回到命令行去git log、git branch、git show。对纯粹用 Gerrit 做 code review 的人来说问题不大但对新人熟悉项目、管理层快速了解代码库、或者排查问题时这种体验就很憋屈。Gitweb 是 Git 官方仓库里自带的一个 Web 界面它的定位就是把裸仓库变成可浏览的网站。树形目录、blame、历史提交、diff、tag/branch 列表、搜索这些功能它全都覆盖。它和 Gerrit 并不冲突反而是互补关系Gerrit 管流程Gitweb 管浏览。1.2 集成之后的实际效果所谓集成核心就是让 Gerrit 的界面里出现指向 Gitweb 的入口并且 Gerrit 能根据当前上下文生成对应 Gitweb 的链接。配置完成之后你会看到项目页上多出一个名为 gitweb名字可自定义的链接点击直接进入该仓库在 Gitweb 中的 summary 页变更详情页里点击某次提交的 SHA-1 时可以通过 gitweb 链接跳到 Gitweb 中这次提交的完整视图一些版本里文件 diff 界面也会有跳转到 Gitweb blob 页的入口。这个过程不需要改 Gerrit 源码也不需要装插件纯靠gerrit.config里的一个配置段就能完成。Gerrit 原生支持对接 gitweb、cgit、gitiles、bitbucket 几种知名仓库浏览器也支持自定义 URL 模板灵活性很大。1.3 适合哪种团队和场景这套组合最适合的是内网自建 Gerrit 做代码托管和审查的小团队。尤其是那种Gerrit 里仓库不少、但一直缺一个统一浏览入口的情况装一个 Gitweb 再配置一下成本极低收益却很直接。如果你们已经有 Gitiles 或其他浏览器思路完全一样只是配置项不同。下面我按最常见的环境——Linux 服务器 Debian/Ubuntu 系 Apache走一遍完整流程。2. 动手前先选型gitweb、cgit、gitiles 还是 custom2.1 四种接入方式的对比Gerrit 的[gitweb]配置段里type字段决定了链接的生成方式。常见几个取值如下type 取值适用场景优点注意点gitweb系统里装了 Gitweb CGI与 Git 同源安装简单链接可深入到 commit/file 层级需要单独配 Apache 和仓库读取权限cgit已部署 cgit 实例页面更轻量、速度快需要额外安装 cgit 并维护其配置gitiles已有 Gitiles 服务和 Gerrit 配合度最高Google 同款Gitiles 本身部署成本偏高适合大团队custom只想给每个项目加一个外部链接配置最省一个 url 搞定通常只能生成项目主页链接无法精细到具体 commit如果你的 Gitweb 实例是独立部署在外网或另一台机器上那么custom是最直接的方案——你只要告诉 Gerrit每个项目对应的 Gitweb 链接长什么样就行了。2.2 我的选型结论对大多数中小团队我推荐直接用type gitweb配合系统自带 Gitweb CGI。理由有三点第一Gitweb 是 Git 官方仓库里就带的东西Debian/Ubuntu 一个 apt 包就能装好不引入额外维护成本第二gitweb类型是 Gerrit 支持得最久、文档最全的对接方式URL 生成规则稳定第三它能生成到具体提交、具体文件的深层链接而不只是仓库主页实用性高出custom一个档次。如果你们团队已经有人在维护 Gitiles那直接配type gitiles更顺手。custom则适合那些Gitweb 部署在别处、图省事先接个入口的过渡场景。选型没有绝对正确答案但先想清楚我要不要点进具体 commit就能很快定下来。3. Gitweb 集成配置完整实操3.1 第一步安装 Gitweb 并让 Apache 跑起来这里以 Debian/Ubuntu 为例。先安装 Apache 和 Gitwebsudo apt update sudo apt install -y apache2 gitweb装完之后Debian 系会自动在/usr/share/gitweb下放置 Gitweb 的界面文件并把gitweb.cgi放在/usr/lib/cgi-bin/。同时它还会生成一个 Apache 配置文件/etc/apache2/conf-available/gitweb.conf内容大致是Alias /gitweb /usr/share/gitweb Directory /usr/share/gitweb Options ExecCGI AddHandler cgi-script .cgi DirectoryIndex gitweb.cgi /Directory这个配置意味着访问http://你的服务器/gitweb/时会执行 Gitweb 的 CGI 脚本。要让配置真正生效还需要启用 Apache 的 cgi 模块并加载这份配置sudo a2enmod cgi sudo a2enconf gitweb sudo systemctl reload apache2然后打开浏览器访问http://服务器IP/gitweb/如果能看到一个仓库列表页面——哪怕现在是空的——就说明 Gitweb 本身已经工作了。这一步卡住的话先别往下走Gitweb 没跑通后面 Gerrit 怎么配都是白搭。3.2 第二步让 Gitweb 能读到 Gerrit 的裸仓库Gitweb 本身并不知道 Gerrit 的存在它只是按自己的配置去某个目录下扫描裸仓库。所以关键是把 Gitweb 的$projectroot指向 Gerrit 实际存储仓库的目录。Gerrit 初始化之后所有仓库都放在站点目录下的git目录里比如典型路径是/home/gerrit/review_site/git。每个项目对应一个裸仓库目录命名是项目名.git子目录项目会按层级再建子目录。打开 Gitweb 的配置文件/etc/gitweb.conf改成如下内容our $projectroot /home/gerrit/review_site/git; our $git_dir $projectroot/$project; our $projects_list $projectroot; our $export_ok ;这里$export_ok 很重要它表示目录下所有 Git 仓库全部对外展示不要额外要求git-daemon-export-ok标记文件。如果你不把这一项置空Gitweb 默认行为是只导出带有那个标记文件的仓库而 Gerrit 创建的仓库默认没有结果就是你看到的仓库列表永远是空的。接着是权限问题。Gerrit 的进程通常以独立用户比如gerrit运行仓库文件归gerrit用户所有而 Apache 的 CGI 进程跑在www-data用户下。如果www-data读不了仓库目录Gitweb 列表照样是空的。最简单的处理办法是把www-data加入gerrit用户组并补齐组读取权限sudo usermod -a -G gerrit www-data sudo chmod gX /home/gerrit sudo chmod -R grX /home/gerrit/review_site/git改完之后刷新 Gitweb 页面应该能看到 Gerrit 里的全部项目了。如果依然空白优先检查路径拼写和权限最直接的办法是用www-data身份去目录里试读取sudo -u www-data ls /home/gerrit/review_site/git3.3 第三步修改 gerrit.config 完成接入Gitweb 自己已经能跑、能列出仓库之后接下来就是在 Gerrit 这边开开关。编辑 Gerrit 站点配置文件$site/etc/gerrit.config比如/home/gerrit/review_site/etc/gerrit.config找到或新建[gitweb]段[gitweb] type gitweb cgiPath /usr/lib/cgi-bin/gitweb.cgi root /home/gerrit/review_site/git linkName gitweb各字段的含义和选值逻辑type gitweb告诉 Gerrit 按 Gitweb 的标准 URL 格式生成链接cgiPathGitweb CGI 在服务器上的实际路径。Gerrit 会以它为基础拼接查询参数形如cgiPath?p项目名.git;asummaryroot仓库根目录必须和 Gitweb 的$projectroot保持一致。这个值用来把磁盘路径映射成 URL 里的项目名填错会导致 Gerrit 生成的链接跳过去 404linkName这个链接在 Gerrit 界面上显示的文字。默认就叫 gitweb你要是想显示成浏览仓库或 Browse改这里就行。保存后重启 Gerrit 让配置生效cd /home/gerrit/review_site/bin ./gerrit.sh restart重启完成后进入 Gerrit 的 Web 界面打开任意一个项目页面就能看到 gitweb 链接了。点进去如果跳到了 Gitweb 里对应仓库的 summary 页说明整条链路已经打通。3.4 备选用 custom 类型接外部 Gitweb如果你手头已经有一套部署在其他域名或端口上的 Gitweb不想再动本机 Apache可以用custom类型。它的原理很简单Gerrit 把 URL 模板里的${project}替换成当前项目名然后生成一个链接。例如[gitweb] type custom url http://git.example.com/gitweb/?p${project}.git;asummary linkName 浏览仓库这种方式的优点是几乎零成本缺点是 Gerrit 无法确认你这套 Gitweb 的 URL 规则所以通常只会生成到仓库主页的链接不会深入到具体 commit 或文件。如果你只是想让同事有个地方能点开看代码这个方案完全够用但如果你希望从 Gerrit 的提交详情直接跳到 Gitweb 的对应 commit 页还是老老实实用标准的gitweb类型更稳妥。4. 常见问题与排查记录配置过程看着不长但每个人环境不一样踩坑的位置也不一样。我把自己实际遇到过、以及身边同事问过的问题整理成了一张速查表再逐个展开说细节。现象常见原因解决办法访问 /gitweb/ 报 403Apache 没启用 cgi 模块执行a2enmod cgi并 reload访问 gitweb.cgi 显示源码缺AddHandler cgi-script .cgi检查 conf 文件里的 handler 配置仓库列表为空$projectroot路径不对或权限不足核对路径检查www-data读取权限仓库列表不全$export_ok设置了标记文件限制把$export_ok置空Gerrit 界面看不到链接[gitweb]没生效或 type 为 disabled修改后重启 Gerrit确认 type 值从 Gerrit 点过去 404cgiPath或root与 Gitweb 实际配置不一致手动在 Gitweb 里打开该项目路径做对比4.1 Apache 层面403 和源码乱码403 一般就是 cgi 模块没启用。确认顺序是a2enmod cgi、a2enconf gitweb、systemctl reload apache2三步缺一不可。另外注意有些环境下 Gitweb 包安装的 conf 文件里没有AddHandler cgi-script .cgi这种情况浏览器会把 CGI 脚本当纯文本吐出来页面不是乱码就是下载一个 .cgi 文件。手动把上面那段 Apache 配置补全再 reload 就行。4.2 仓库列表为空或不全这是 Gitweb 侧最典型的故障。第一查路径$projectroot和 Gerrit 实际的git目录是否一致别有符号链接绕来绕去第二查权限sudo -u www-data ls $projectroot能不能看到目录内容第三查$export_ok如果你没有把它显式置空而系统的默认又恰好配置成git-daemon-export-ok那仓库永远不会出现。我的建议是配置里明确写好our $export_ok ;避免依赖发行版默认值。4.3 Gerrit 界面上没有链接先确认配置文件写对了位置[gitweb]段必须放在gerrit.config根级别别不小心写进[gerrit]段里面了。然后确认type不是disabled。最后也是最容易忘的一步必须重启 Gerrit。Gerrit 对这份配置不是热加载的不重启就等于没改。重启后如果还是没有打开浏览器开发者工具看项目页 HTML 里有没有包含 gitweb 字样能帮你判断是生成端问题还是前端渲染问题。4.4 从 Gerrit 跳转后 404这类问题集中在 URL 拼接结果和 Gitweb 路由不匹配。比如 Gitweb 实际的项目名是infra/scripts.gitGerrit 生成的却是infra%2Fscripts.git或者反过来多了一个.git后缀。排查时不要猜直接把 Gerrit 生成的链接复制出来手动改到 Gitweb 能访问的形式比对差异就清楚了。root参数在这里面扮演的角色很关键它决定了 Gerrit 如何把项目名映射到磁盘路径所以务必和 Gitweb 的$projectroot严格保持一致。5. 踩坑之后的一些心得整套流程走下来我对配置这件事最大的体会是三分靠配置七分靠权限剩下九十分靠路径对齐。无论是root、cgiPath、$projectroot本质上都是同一件事——让 Gerrit 认识的仓库、和 Gitweb 能读到的仓库是同一个仓库。还有一点必须提醒Gitweb 集成之后它会独立于 Gerrit 的权限体系存在。如果你的 Gerrit 里有私有项目而 Gitweb 的仓库目录对全员可读那就等于把私有代码暴露了。Gerrit 的访问控制和 Gitweb 的访问控制是两套系统这一点很容易被忽略。我个人的做法是要么在 Gitweb 侧用$strict_export配合标记文件精确控制导出范围要么把 Gitweb 部署在只有内网可访问的网段同时在重复一遍——私有仓库绝对不要随便全局列出来。最后分享一个小技巧linkName不只是改个文字而已。如果团队里有人不熟悉 Gitweb把链接名字改成浏览仓库或代码浏览能显著减少这个 gitweb 是干嘛的这种问题。多花十秒钟改一行配置省掉以后无数次的解释成本这笔账非常划算。