ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Git+Repo+Gerrit代码服务器搭建:权限控制与代码评审全流程

Git+Repo+Gerrit代码服务器搭建:权限控制与代码评审全流程 简介这套资料围绕 Git、Repo、Gerrit 三大工具完整梳理代码评审服务器的搭建全流程适合运维工程师、持续集成搭建人员及希望自建代码托管与评审环境的开发者。文档从名词解释、必要软件安装讲起覆盖 Gitosis 管理员创建、公钥配置、Repo 服务器部署、Git 守护进程启动再到 Gerrit 配置与代码评审开启各环节配有具体命令和操作序列便于按步骤落地。资源包含 1 个 docx 文件压缩包大小约 294KB核心内容以图文步骤形式呈现适合边看边操作。已有 3134 人学习下载。通过这份资料读者可快速理解从 Git 基础服务到 Gerrit 评审环境的整体架构掌握多仓库管理manifest与权限配置思路避免搭建过程中常见的环境、权限与守护进程启动问题提高服务器搭建效率。1. GitRepoGerrit 代码服务器搭建从权限到评审的完整闭环团队代码量过了某个临界点之后单机 Git 仓库加手写 SSH 公钥那一套就会开始失控——有的人只该读不该写有的人需要拉多个仓库但每次都要单独 clone。GitRepoGerrit 这套组合的典型形态是gitosis 管 Git 层的用户权限repo 通过 manifest 仓库管理一堆项目仓库的同步Gerrit 在最外层做代码评审。本文按真实搭建顺序走完这套流程从 gitosis 安装、repo 配置 default.xml到 Gerrit 的 gerrit.config、apache2 反向代理与 htpasswd 认证每个步骤的坑都会点出来。适合想在公司内网搭建一套完整代码托管和评审环境的运维或团队负责人也适合想搞明白这几个工具之间如何配合的开发者。2. 先搭 Git 基础服务gitosis 权限控制与 git-daemon 匿名拉取2.1 为什么先装 gitosis权限不落地后面全是空谈很多教程上来就装 Gerrit但 Gerrit 默认接管的是「评审」这一层底层的 Git 仓库权限如果没人管任何一个能 ssh 到服务器的用户都能直接 push。gitosis 的工作就是把 Git 仓库的读写权限收拢到一个配置文件里通过一个专用的 git 系统用户来执行 Git 操作。这样团队成员不需要在服务器上有真实 shell 账号公钥放进 keydir 目录、权限写进 gitosis.conf就完成了权限下发。整个链路里gitosis 是最轻量的一层。它不提供 Web 界面不需要数据库全部配置都通过一个叫 gitosis-admin 的 Git 仓库来管理——改配置就是 commit 一次配置仓库这个设计在当年很超前也值得后来用 Gerrit 的人理解Gerrit 的 refs/for/master 评审流本质上也是把「改配置/提交代码」变成一次带审核的 Git 操作。2.2 安装 gitosis 的完整流程与参数说明服务端先安装基础软件然后创建 git 系统用户。这里用--disabled-password而不是直接passwd设置密码目的是让 git 用户无法通过密码登录只能通过公钥认证执行gitosis-init和后续 Git 命令这是安全基线不是可选项。sudo apt-get install git-core openssh-server openssh-client python-setuptools # 下载 gitosis 源码包 mkdir ~/gitosis_setup cd ~/gitosis_setup git clone http://github.com/res0nat0r/gitosis.git cd gitosis sudo python setup.py install # 创建禁用密码的系统用户 git sudo adduser --system --shell /bin/sh --gecos git SCM user --group --disabled-password --home /home/git git逻辑说明python setup.py install会把 gitosis 的命令安装到系统路径如果这一步报找不到 setuptools说明 python-setuptools 没装或装的不对。adduser的参数拆开看--system表示创建系统账户--shell /bin/sh限制登录 shell--group同时创建同名用户组--home /home/git指定家目录。这样 git 用户就是一个只能执行推送、拉取操作的服务账户。关键参数说明gitosis 的下载地址在原项目里用的是 git:// 协议如果公司内网封了 9418 端口直接用 http 地址替代即可这里写的 github http 地址是备选方案里更稳的一个。2.3 管理员公钥注入与 gitosis-admin 配置仓库在客户端生成一对密钥把公钥传到服务器 /tmp 目录然后由 git 用户执行gitosis-init公钥会被写入 git 用户的 authorized_keys同时服务器上会生成/home/git/repositories/gitosis-admin.git。这个仓库就是管理 gitosis 配置的入口。# 客户端操作 ssh-keygen -t rsa scp ~/.ssh/id_rsa.pub sykean192.168.1.252:/tmp/id_rsa_admin.pub # 服务器端操作 cd /tmp sudo chmod 777 id_rsa_admin.pub sudo -H -u git gitosis-init id_rsa_admin.pub sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update逻辑说明gitosis-init id_rsa_admin.pub是重定向标准输入把公钥内容喂给初始化程序它会把公钥添加到 git 用户的 authorized_keys 中并完成 gitosis-admin 仓库的初始化。chmod 755 post-update这一步容易被忽略——post-update 是 Git 的 hook 脚本权限不对会导致 gitosis-admin 仓库 push 之后配置不生效。然后回到客户端把 gitosis-admin 仓库 clone 下来目录下有两个核心东西gitosis.conf是权限配置文件keydir/是所有成员的公钥目录。添加新成员就是把他的公钥放进去然后在 gitosis.conf 里给他授权最后 commit 并 push 回服务器。这个操作要严格遵循「拉取-改-推送」三个步骤避免直接在服务器上改文件否则下次 clone 时配置会冲突。mkdir -p ~/git cd ~/git git clone git192.168.1.252:gitosis-admin.git cd gitosis-admin ls -la # 看到 keydir/ 和 gitosis.conf 就说明初始化成功2.4 启动 git-daemon让只读仓库可以被匿名拉取gitosis 解决的是需要认证的读写操作但 repo 客户端在首次 init 的时候会尝试访问一些基础仓库。如果服务器不想为每个只读场景都下发公钥可以额外起一个 git-daemon专门提供匿名只读服务。这一步在原文档里是通过 git-daemon-run 管理的实际配置就动一个文件。sudo apt-get install git-daemon-run sudo vim /etc/sv/git-daemon/run启动命令核心是这一行把原来的--base-path/var/cache/git改成 repositories 目录并加上--export-all和--enablereceive-packexec chpst -ugitdaemon \ git daemon --export-all --enablereceive-pack \ --base-path/home/git/repositories参数说明--export-all表示不对仓库做 export 标记检查只要在 base-path 下的仓库都能被访问--enablereceive-pack开启匿名推送能力如果只需要只读把这段去掉即可。改完后重启守护进程sudo sv stop git-daemon sudo sv start git-daemon # 或者直接 sudo sv restart git-daemon注意git-daemon 跑起来后git clone git://192.168.1.252/project1.git这种匿名拉取才能通。如果后续 Gerrit 接管了仓库的评审流这个 daemon 可以只保留只读能力避免匿名推送绕过评审。3. Repo 多仓库管理manifest 仓库、default.xml 与测试仓库3.1 下载安装 repo两个 clone 地址与 /usr/bin 放置方式repo 是 Google 为多仓库 Android 项目设计的工具它本身是一个 Python 脚本通过 manifest 仓库里的 default.xml 描述「要拉哪些项目、放到哪个目录」。安装方式很简单把 repo 脚本放到 /usr/bin 下但要先确认脚本里的 REPO_URL 指向哪个仓库——如果服务器在内网建议改成内网可达的 git-repo 镜像地址。mkdir -p ~/gitCfg cd ~/gitCfg git clone http://gerrit.googlesource.com/git-repo git-repo.git # 如果上面的地址连不上可以尝试 # git clone http://review.mfunz.com/git-repo git-repo.git cd git-repo sudo cp repo /usr/bin/repo sudo chmod 755 /usr/bin/repo参数说明REPO_URL变量默认指向 googlesource 的仓库外网环境不稳定时repo 执行同步操作会卡住。遇到阿里的镜像或者内网镜像时直接把 /usr/bin/repo 里的 REPO_URL 改掉即可。这个字段在脚本顶部搜索REPO_URL 就能看到。repo 工具本身不复杂复杂的是它如何与服务端的 manifest 仓库配合。repo init 时指定的 -u 参数就是 manifest 仓库的地址repo sync 时它会读取 default.xml把其中定义的每个 project 仓库依次 clone 到本地指定路径。理解了这条链路后面配置 default.xml 就不会懵。3.2 创建 manifest 仓库并配置 default.xml先在服务器的 repositories 目录下初始化一个空的 manifest.git 仓库再从客户端 clone 下来写 default.xml。xml 里project标签的 name 是远程仓库名path 是本地路径缺省 path 时直接用 name。三个测试仓库的配置示例如下?xml version1.0 encodingUTF-8? manifest remote nameorigin fetch.. reviewhttp://192.168.1.252:8080/ / default remoteorigin revisionmaster / project nameproject1 pathproject1 / project nameproject2 pathproject2 / project nameproject3 pathproject3 / /manifest字段说明remote里的fetch..是相对路径写法表示在 manifest 仓库的上一级目录找同名仓库review字段是给 Gerrit 用的repo upload 会通过这个地址推送评审。如果服务器 IP 变化只需改动这一个文件里的 remote 段所有客户端重新 repo sync 就能生效。写完 xml 后推送到远端cd ~/repo git clone git192.168.1.252:manifest.git cd manifest vim default.xml git add default.xml git commit -m Init default.xml default.xml git push origin master注意如果后面接 Gerrit这里的 push 要改成git push origin HEAD:refs/for/master否则直接推到 master 会绕过 Gerrit 的评审规则。作者原文也明确写了这一点这是很多第一次接 Gerrit 的人最容易翻车的地方。3.3 建立三个测试仓库并验证 repo sync服务器端进入 repositories 目录分别建立三个裸仓库并把属主改成 git 用户最后放宽目录权限。这一步是关键Gerrit 起来之后它是以 gerrit 系统用户身份去读写这些仓库的如果目录属主还是 rootGerrit 端会出现仓库无法访问的报错。cd /home/git/repositories git init --bare project1.git git init --bare project2.git git init --bare project3.git # 修改仓库属主与权限方便 git 用户和后续 gerrit 用户访问 sudo chown -R git:git /home/git/repositories/project1.git sudo chmod 777 -R /home/git/repositories/project1.git \ project2.git project3.git客户端验证环节先把空仓库 clone 到本地随便建几个文件提交后推送cd ~/repo git clone git192.168.1.252:project1.git cd project1 echo # project1 README.md git add README.md git commit -m init project1 git push origin master逻辑说明三个仓库在服务器端是独立的裸仓库但客户端可以分散操作repo 的 default.xml 只是把它们在逻辑上绑定成一个「项目集」。测试 repo 同步时在另一个目录执行 repo init 和 repo sync如果三个目录都能拉下来说明 manifest 配置正确。mkdir ~/repotest cd ~/repotest repo init -u git192.168.1.252:manifest.git repo sync4. Gerrit 安装与配置gerrit.config 参数、apache2 反向代理与认证链路4.1 Java 环境与 gerrit-2.11.war 初始化gerrit 是 Java 应用先搞定 JDK。原文档用的是 jdk-7u45-linux-i586.tar.gz这个版本比较老实际操作中用 jdk-8 或 jdk-11 版本同样可行但要注意 gerrit-2.11 对 Java 版本的兼容性建议先用 1.7 或 1.8 保证顺利跑通。安装过程就是解压 tar 包、配置环境变量。sudo adduser gerrit sudo passwd gerrit su gerrit sudo tar zxvf ./jdk-7u45-linux-i586.tar.gz -C /opt vim ~/.bashrc # 在文件末尾追加以下内容 JAVA_HOME/opt/jdk1.7.0_45 export JRE_HOME$JAVA_HOME/jre export CLASSPATH$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH export PATH$JAVA_HOME/bin:$JRE_HOME/bin:$PATH环境变量配置完后source ~/.bashrc并执行java -version确认生效。然后下载 gerrit-2.11.war 并执行初始化java -jar gerrit-2.11.war init -d review_site初始化向导会问一堆问题大部分可以直接回车使用默认值但有两个要特别注意数据库选默认 H2 即可单机场景不需要额外装 MySQLBehind reverse proxy [y/N]?这里要输入 y因为后面要用 apache2 做反向代理如果不选 ygerrit 的回调地址会直接暴露 8081 端口登录会有跳转问题。4.2 gerrit.config 逐项拆解认证方式、SSH 端口与邮件配置初始化完成后生成的配置文件在review_site/etc/gerrit.config。原文给出的完整配置一次看全有点花核心几个字段拆开理解配置段关键参数含义与注意事项gerritbasePath git仓库根目录相对于 review_site 的路径最终指向服务器的 repositories 目录gerritcanonicalWebUrl http://192.168.1.252:8081/gerrit 对外访问地址注意 IP 要改成你自己的authtype HTTP认证交给 apache2 的 Basic Authgerrit 自身不维护密码只认登录后的用户名sendemailsmtpServer / smtpPort / smtpEncryption用企业邮箱 SMTP 时465 端口必须配 SSL如果不用邮件验证可以跳过sshdlistenAddress *:29418Gerrit 的 SSH 端口repo 和 ssh 操作都走这里httpdlistenUrl proxy-http://*:8081/关键点proxy- 前缀表示接受代理转发不是直连访问databasetype h2默认嵌入式数据库仓库规模大了再考虑迁移 PostgreSQLauth type HTTP的含义要理解透gerrit 不存储密码用户在浏览器访问时apache2 先把账号密码拦下来做 Basic Auth 验证验证通过后把用户名传给 gerrit。而 gerrit 自己维护一份用户数据库记录用户权限和 SSH 公钥。所以「apache2 通过认证」和「gerrit 有该用户记录」是两回事这正好对应本文后面避坑章要讲的问题。邮件配置在第一次登录时比较重要因为 gerrit 注册用户会尝试发送验证邮件。如果内网没有可用 SMTP可以在etc/mail放一个假的 sendmail wrapper或者直接用git config层面的替代方案但最省事的还是填一个真实可用的企业邮箱 SMTPsmtpServerPort 对 465 时记得 smtpEncryption SSL。4.3 apache2 反向代理与 htpasswd 账号体系apache2 在这里不是给 gerrit 做负载均衡而是做两件事把 8080 端口收到的请求转发到 gerrit 的 8081以及在转发前做一层 Basic Auth 口令认证。这样用户记住 8080 端口即可8081 不直接暴露。先开启 apache2 的代理和 rewrite 模块cd /etc/apache2/mods-enabled ln -s ../mods-available/proxy.load ln -s ../mods-available/proxy.conf ln -s ../mods-available/proxy_http.load ln -s ../mods-available/rewrite.load然后配置端口监听。原文在 /etc/apache2/port.conf 里添加了 8080 和 NameVirtualHost 配置当前主流的 apache2 版本一般用Listen 8080即可NameVirtualHost 指令在 2.4 版本已废弃写了反而会被警告。这一步按自己服务器的 apache 版本调整不要盲目照抄旧文档。重点在反向代理配置原文档的 httpd.conf 位置因发行版而异Ubuntu 下通常在 /etc/apache2/conf-available/ 里新建文件并启用VirtualHost *:8080 ServerName 192.168.1.252 ProxyRequests Off ProxyVia Off ProxyPreserveHost On AllowEncodedSlashes On RewriteEngine On RewriteRule ^/(.*) http://192.168.1.252:8081/$1 [NE,P] Proxy * Order deny,allow Allow from all /Proxy Location /login/ AuthType Basic AuthName Gerrit Code Review Require valid-user AuthBasicProvider file AuthUserFile /home/gerrit/review_site/etc/passwd /Location ProxyPass / http://192.168.1.252:8081/ /VirtualHost关键点是Location /login/这一段它只对 gerrit 的登录路径做认证拦截其他路径如静态资源、REST API直接透传。AuthUserFile 指向的 passwd 文件由 htpasswd 管理首次创建用touch /home/gerrit/review_site/etc/passwd htpasswd -b /home/gerrit/review_site/etc/passwd admin admin这段命令创建了一个用户名为 admin、密码为 admin 的 HTTP 认证账号。之后追加用户用htpasswd -b ./review_site/etc/passwd UserName PassWord注意这个账号只在 apache2 层面有效gerrit 数据库里还没有对应记录第一次用 admin 登录 gerrit Web 界面时gerrit 才会自动创建同名账号且第一个登录的账号默认成为管理员User ID: 1000000。最后启动服务和重启 apachereview_site/bin/gerrit.sh start sudo /etc/init.d/apache2 restart浏览器访问http://192.168.1.252:8080/弹出认证框输入 admin/admin通过后 gerrit 会引导设置全名和邮箱。这里邮箱要填真实地址后续 Gerrit 会向该地址发送通知。5. Gerrit 搭建避坑认证关联、代理改写与仓库权限5.1 现象htpasswd 创建的用户登录后要求手动输入 gerrit 用户名而不是自动关联原因htpasswd 账号和 gerrit 数据库账号是两个独立体系。如果 gerrit 数据库里已经存在同名用户比如之前通过 ssh 命令创建过同名账号Web 登录时 apache 认证通过了但 gerrit 发现同名但无法确认是否同一个人就会要求手动输入 Gerrit 用户名并可能创建出重复用户。解决第一次登录前确认 gerrit 数据库中没有同名用户。如果已经出现重复到 Gerrit Web 端 Settings 里把旧账号的公钥和权限迁移过去或者通过gerrit flush-caches --cache ldap_usernames如果用了 LDAP刷新。最简单粗暴的办法是清掉 H2 数据库重新初始化但那样项目权限全部重来所以建议第一次登录前不要用 ssh 命令创建同名用户。5.2 现象gerrit Web 界面能打开但登录回调后跳转到 8081 端口浏览器直接连不上原因canonicalWebUrl和httpd.listenUrl配置不一致。如果 canonicalWebUrl 填的是http://192.168.1.252:8081/而 apache2 代理端口是 8080gerrit 生成的跳转链接直接指向 8081而 8081 端口只听proxy-http://不接受普通 HTTP 访问于是出现「登录页面正常登录后白屏或拒绝连接」。解决所有对外 URL 统一写成 8080 端口的地址。canonicalWebUrl http://192.168.1.252:8080/只有httpd.listenUrl保持proxy-http://*:8081/不变。记住这个原则对外永远 8080内部代理永远 8081。5.3 现象Gerrit 可以登录但创建项目后git clone ssh://...提示仓库不存在或权限错误原因gerrit 的basePath git是相对于 review_site 目录的如果实际仓库在/home/git/repositories下需要确认 gerrit 配置里的 basePath 是否指向了一致的目录。另外 repository 目录的属主如果不是 gerrit 用户Gerrit 进程没有写权限。解决确认配置里 basePath 的实际路径指向/home/git/repositories可以通过ls -la看目录属性然后用sudo chown -R gerrit:gerrit /home/git/repositories把仓库权限交给 gerrit。再执行一次chmod 755 post-updatehook避免 push 后 hook 无执行权限。5.4 现象repo sync 能拉代码但 repo upload 推送评审时报错fatal: Not a git repository: ...或认证失败原因repo 客户端的 manifest 仓库里 remote 的 review 地址没配对。如果 default.xml 的remote review字段写成 8081 端口而 apache2 只暴露 8080repo upload 就不知道往哪推。另一个常见原因是 SSH 端口用的是 29418repo 客户端没有正确使用这个端口。解决default.xml 里 review 地址用http://192.168.1.252:8080/repo init 时用带端口的地址repo init -u ssh://admin192.168.1.252:29418/manifest.git。repo 工具的 SSH 端口从 manifest 仓库 URL 继承所以 init 时就要写对。5.5 现象修改 apache2 配置后重启登录 /login/ 路径出现 403 或 500原因Location /login/块放在 ProxyPass 之后的语法冲突或者 AuthUserFile 路径不对apache2 无法读取 passwd 文件。还有可能是文件在 /home/gerrit 目录下apache2 的 www-data 用户无权读取。解决把 httpd.conf 的配置块顺序调整Location块放在 ProxyPass 之前明确 passwd 文件权限为sudo chmod 644 /home/gerrit/review_site/etc/passwd并检查 apache2 错误日志/var/log/apache2/error.log里的具体报错信息。改完配置先sudo apache2ctl configtest验证语法再重启 apache2。6. Gerrit 接入后的日常流创建项目、SSH 验证与 refs/for 评审推送Gerrit 起来之后日常操作和标准 Git 有一处关键差异推送代码不能直接推 master而要推到refs/for/master这会让每一次 push 变成一条待评审的 change只有评审通过合入才会进入主干。这是 Gerrit 和 Gitosis、Gitea 这类工具的核心区别。先验证 SSH 通道。Gerrit 的 SSH 端口是 29418用户需要在 Web 端 Settings 里添加个人公钥然后用下面命令做连通性测试ssh -p 29418 admin192.168.1.252看到欢迎信息说明 SSH 配置成功用户识别和公钥关联没问题。接下来创建一个测试项目Gerrit 不像 gitosis 那样手动在服务器建裸仓库而是通过 SSH 命令直接创建ssh -p 29418 admin192.168.1.252 gerrit create-project --empty-commit --name test创建完成后服务器端 git 目录和 Gerrit Web 端 Projects - List 里都会出现 test 项目。然后按 Gerrit 方式推送代码manually 初始化一个仓库修改代码addcommit最后 push 到评审分支。mkdir test cd test git init git remote add origin ssh://admin192.168.1.252:29418/test.git echo # test README.md git add README.md git commit -m init test git push origin HEAD:refs/for/masterpush 成功后打开 Gerrit Web 界面在 My - Changes 里能看到这条待评审记录评审人点 Review 进入代码评审页面打分并提交。合入后管理员执行gerrit review或直接在 Web 端点 Submit代码才会进入 test 分支。repo 拉取多仓时的经典流程是和前面章节的机制串联起来的manifest 仓库本身在 Gerrit 上创建default.xml 通过refs/for/master评审合入然后客户端 repo init 时用ssh://userhost:29418/manifest.git作为清单库地址repo sync 会根据已合入的 default.xml 拉取所有 project。整个链路是Gerrit 管理评审和权限manifest 仓库描述项目结构repo sync 做多仓同步git push 到 refs/for/master 进入评审循环。从那以后我每次搭 Gerrit 环境都强制走一遍这个顺序先确认 gerrit.config 里 canonicalWebUrl 用的是对外端口、再检查 basePath 指向的目录属主、最后用repo init -u拉一遍空仓库验证 manifest。这套检查半小时内能提前避开 80% 的登录跳转和权限问题希望帮到你。本文还有配套的精品资源点击获取
返回列表