1. 自建Git服务的选型逻辑与核心考量
1.1 为什么2025年还要自己搭Git服务
先说一个我自己的真实感受。过去几年,身边不少团队把代码托管到公有云平台上,省事、省心、不用运维。但到了2024年下半年开始,陆续有团队找我咨询自建Git服务的事,原因五花八门:有的是因为团队规模上来了,按席位付费的成本已经超过自建服务器;有的是因为合规要求,代码不能放在外部;还有的是因为CI/CD流水线跑得太频繁,公有云的分钟数套餐根本不够用。
自建Git服务这件事,本质上是在成本、可控性、运维负担三者之间找一个平衡点。你省下了订阅费,但你要自己维护服务器、做备份、处理升级、盯安全漏洞。所以选型的第一步不是看哪个软件功能多,而是先想清楚:你的团队到底需要什么。
我把常见的需求场景分成三类:
- 小团队(3-15人):核心诉求是轻量、好装、够用。不需要复杂的代码评审流程,能管代码、能看提交记录、能简单协作就行。这类场景下,Gitea几乎是默认答案。
- 中型团队(15-100人):开始需要CI/CD集成、代码评审、权限细分、Issue跟踪、Wiki等完整功能。GitLab社区版是这个区间的首选,功能全、生态好、文档丰富。
- 有严格代码评审需求的团队:比如需要强制Code Review、需要精细到行级的评审记录、需要和CI系统深度绑定。Gerrit就是为这个场景生的,虽然学习曲线陡,但评审流程的严谨程度是另外两个没法比的。
1.2 三款工具的核心定位差异
很多人把Gitea、GitLab、Gerrit放在一起比,其实它们的定位差别很大,不是简单的“谁好谁坏”。
Gitea是用Go语言写的轻量级Git服务,一个二进制文件就能跑起来,资源占用极低。它的设计哲学是“够用就好”,不追求大而全,但该有的功能都有。你可以把它理解成一把瑞士军刀——小巧、便携、关键时刻都能派上用场。
GitLab是一个完整的DevOps平台,Git仓库只是它的一部分。它包含了CI/CD、容器 registry、安全扫描、项目管理、监控告警等一整套工具链。用GitLab,你其实是在用一个平台,而不是一个单纯的Git服务。代价就是资源消耗大,官方推荐至少4核8G起步,实际跑起来8G内存是底线。
Gerrit的定位更特殊,它本质上是一个代码评审系统,Git仓库是它的底层存储。Gerrit的核心价值在于它的评审流程:每一次提交都要经过Review才能合入,支持行级评论、投票机制、权限控制。Android项目就是用Gerrit管理的,你可以想象它对评审流程的严谨程度。
1.3 选型决策的关键维度
我整理了一个对比表格,把三个工具在关键维度上的表现列出来,方便你快速判断:
| 维度 | Gitea | GitLab CE | Gerrit |
|---|---|---|---|
| 最低内存要求 | 128MB | 4GB(推荐8GB) | 2GB(推荐4GB) |
| 安装复杂度 | 极低(单二进制) | 中等(Docker/Omnibus) | 较高(Java环境+数据库) |
| Web界面友好度 | 高 | 高 | 中等(偏开发者) |
| CI/CD集成 | 内置Actions(轻量) | 内置完整CI/CD | 需配合Jenkins等 |
| 代码评审 | 基础PR/MR | 完整MR流程 | 专业级评审流程 |
| 权限管理 | 基础 | 细粒度 | 极细粒度 |
| 学习曲线 | 平缓 | 中等 | 陡峭 |
| 适用规模 | 小团队 | 中大型团队 | 有严格评审需求的团队 |
选型的时候,我建议你先问自己三个问题:第一,团队有多少人,未来一年会扩展到多少?第二,有没有专职的运维人员?第三,代码评审流程需要多严格?这三个问题的答案基本就能锁定你的选择。
注意:不要因为“功能多”就选GitLab,也不要因为“轻量”就选Gitea。选型的核心是匹配当前需求,同时留出一定的扩展空间。过度设计带来的运维负担,往往比功能不足更让人头疼。
2. Gitea部署实践与核心配置详解
2.1 Linux环境下Gitea的安装方式选择
Gitea的安装方式有好几种:二进制直接跑、Docker部署、包管理器安装、从源码编译。我实测下来,最推荐的是二进制+Docker混合方案——用Docker跑数据库,二进制跑Gitea本体。这样既保证了数据库的稳定性和易维护性,又让Gitea本体保持轻量和高效。
当然,如果你追求极致的简单,全部用Docker Compose编排也是可以的。下面我给出两种方案的详细步骤。
方案一:二进制安装(推荐用于生产环境)
先创建一个专用用户,不要用root跑Gitea:
sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' \ --group --disabled-password --home /home/git git然后下载对应架构的二进制文件。截至2025年初,Gitea的最新稳定版是1.22.x系列:
wget -O gitea https://dl.gitea.com/gitea/1.22.6/gitea-1.22.6-linux-amd64 chmod +x gitea sudo mv gitea /usr/local/bin/创建目录结构:
sudo mkdir -p /var/lib/gitea/{custom,data,log} sudo chown -R git:git /var/lib/gitea/ sudo chmod -R 750 /var/lib/gitea/ sudo mkdir /etc/gitea sudo chown root:git /etc/gitea sudo chmod 770 /etc/gitea这里有个细节:/etc/gitea目录的权限设置成770,属主是root,属组是git。这样Gitea进程能读写配置,但其他用户无法访问。安装完成后可以改成750更安全。
方案二:Docker Compose部署(推荐用于测试和快速验证)
version: "3" services: gitea: image: gitea/gitea:1.22.6 container_name: gitea environment: - USER_UID=1000 - USER_GID=1000 - GITEA__database__DB_TYPE=postgres - GITEA__database__HOST=db:5432 - GITEA__database__NAME=gitea - GITEA__database__USER=gitea - GITEA__database__PASSWD=gitea_password restart: always volumes: - ./gitea:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro ports: - "3000:3000" - "222:22" depends_on: - db db: image: postgres:16-alpine container_name: gitea_db restart: always environment: - POSTGRES_USER=gitea - POSTGRES_PASSWORD=gitea_password - POSTGRES_DB=gitea volumes: - ./postgres:/var/lib/postgresql/data这个Compose文件里,我把数据库单独拆出来,用PostgreSQL而不是Gitea默认的SQLite。原因很简单:SQLite在并发写入时会有锁竞争,团队人数超过5个之后,偶尔会出现提交卡顿的情况。PostgreSQL虽然多了一个容器,但稳定性提升非常明显。
2.2 配置文件的关键参数调优
Gitea的配置文件在/etc/gitea/app.ini(二进制安装)或/data/gitea/conf/app.ini(Docker安装)。有几个参数我踩过坑,这里重点说一下。
服务器域名和SSH端口:
[server] DOMAIN = git.yourdomain.com SSH_DOMAIN = git.yourdomain.com HTTP_PORT = 3000 ROOT_URL = https://git.yourdomain.com/ SSH_PORT = 222ROOT_URL必须和实际访问地址完全一致,包括协议(http/https)和末尾的斜杠。我见过好几次因为ROOT_URL配错导致Webhook回调失败、头像加载不出来的情况。
仓库默认分支和合并方式:
[repository] DEFAULT_BRANCH = main DEFAULT_MERGE_STYLE = merge如果你团队习惯用master作为默认分支,把DEFAULT_BRANCH改成master。DEFAULT_MERGE_STYLE有三个选项:merge、rebase、rebase-merge。我一般推荐merge,因为它在Git历史里保留了完整的合并记录,排查问题时更容易追溯。
关于“gitea 合并指定合并人”这个需求,Gitea本身没有直接的“指定合并人”功能,但可以通过分支保护规则来实现类似效果。在仓库设置里,找到“分支保护规则”,添加规则后勾选“启用合并白名单”,然后指定哪些用户或团队有合并权限。这样只有白名单里的人才能点合并按钮,其他人只能提交PR。
2.3 反向代理与HTTPS配置
生产环境一定要上HTTPS,不然SSH密钥和密码在网络上裸奔。我用Nginx做反向代理,配置如下:
server { listen 443 ssl http2; server_name git.yourdomain.com; ssl_certificate /etc/letsencrypt/live/git.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/git.yourdomain.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } client_max_body_size 512M; }client_max_body_size这个参数一定要调大,默认的1M根本不够用。团队里只要有人推了一个包含大文件的提交,就会报413错误。我一般设成512M,基本够用。
2.4 Gitea Actions的轻量CI实践
Gitea 1.19之后内置了Actions功能,语法和GitHub Actions基本兼容。对于小团队来说,这已经足够跑单元测试和自动构建了。
启用Actions需要在配置里打开:
[actions] ENABLED = true然后在仓库里创建.gitea/workflows/test.yml:
name: Run Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.22' - name: Run tests run: go test ./...这里有个坑:Gitea Actions的runner需要单独部署。官方提供了act_runner,你可以用Docker跑:
docker run -d --name gitea-runner \ -v /var/run/docker.sock:/var/run/docker.sock \ -e GITEA_INSTANCE_URL=https://git.yourdomain.com \ -e GITEA_RUNNER_REGISTRATION_TOKEN=<your-token> \ gitea/act_runner:latest注册Token在Gitea的“站点管理”→“Actions”→“Runners”页面获取。注意runner的标签要和workflow里的runs-on匹配,默认是ubuntu-latest。
实操心得:Gitea Actions的日志输出有时候会延迟,特别是任务失败的时候。如果你发现任务卡住了,先去runner容器里看日志,
docker logs gitea-runner,大概率能找到原因。我遇到过因为Docker socket权限问题导致runner无法创建容器的情况,把runner用户加入docker组就好了。
3. GitLab社区版部署与运维实战
3.1 Docker部署GitLab的内存优化方案
GitLab社区版的Docker镜像用起来很方便,但内存占用是出了名的大。官方推荐8GB,实际跑起来如果不管不顾,16GB都能给你吃满。我在一台4核8G的机器上部署过,通过调优把内存控制在了5GB左右,这里把经验分享出来。
首先,Docker Compose文件这样写:
version: "3.6" services: gitlab: image: gitlab/gitlab-ce:16.11.0-ce.0 container_name: gitlab restart: always hostname: 'gitlab.yourdomain.com' environment: GITLAB_OMNIBUS_CONFIG: | external_url 'https://gitlab.yourdomain.com' gitlab_rails['gitlab_shell_ssh_port'] = 2222 puma['worker_processes'] = 2 sidekiq['max_concurrency'] = 10 postgresql['shared_buffers'] = "256MB" postgresql['max_worker_processes'] = 4 prometheus_monitoring['enable'] = false gitlab_rails['prometheus_address'] = '0.0.0.0:9090' ports: - '80:80' - '443:443' - '2222:22' volumes: - './config:/etc/gitlab' - './logs:/var/log/gitlab' - './data:/var/opt/gitlab' shm_size: '256m'关键调优参数说明:
puma['worker_processes'] = 2:Puma是GitLab的Web服务器,默认worker数量等于CPU核心数。对于小团队,2个worker足够了,能省下不少内存。sidekiq['max_concurrency'] = 10:Sidekiq处理后台任务,默认25的并发在低配机器上会导致内存飙升。降到10之后,后台任务处理速度略慢,但内存稳定很多。prometheus_monitoring['enable'] = false:GitLab自带的监控组件非常吃资源,小团队根本用不上,直接关掉。postgresql['shared_buffers'] = "256MB":数据库共享缓冲区,默认值偏高,调小一点对性能影响不大。
这套配置在4核8G的机器上跑,稳定运行了半年多,日常使用没有明显卡顿。
3.2 项目导入与代码迁移的完整流程
“gitlab导入项目”是热词里出现频率很高的需求。GitLab支持从多种来源导入项目,包括GitHub、Bitbucket、Gitea、以及普通的Git仓库。我重点说两种最常用的方式。
方式一:通过URL导入(适合从其他平台迁移)
在GitLab首页点击“新建项目”→“导入项目”→“通过URL导入”。填入源仓库的HTTPS地址,如果是私有仓库,还需要填入用户名和密码(或访问令牌)。
这里有个坑:如果源仓库很大(超过1GB),导入过程可能会超时。GitLab默认的导入超时时间是2小时,可以在gitlab.rb里调整:
gitlab_rails['import_export_max_time'] = 7200方式二:本地已有仓库推送到GitLab指定仓库
这是最常见的场景。假设你在本地已经有一个Git仓库,现在要推送到GitLab上新建的仓库:
# 进入本地仓库目录 cd /path/to/your/repo # 添加GitLab远程仓库 git remote add gitlab https://gitlab.yourdomain.com/group/project.git # 推送所有分支和标签 git push gitlab --all git push gitlab --tags如果你想把本地仓库推送到GitLab上已有的仓库(比如仓库里已经有README文件),需要先拉取远程内容:
git remote add gitlab https://gitlab.yourdomain.com/group/project.git git fetch gitlab git rebase gitlab/main git push gitlab main注意:如果远程仓库有保护分支,直接push可能会被拒绝。你需要先在GitLab的“设置”→“仓库”→“保护分支”里,把对应分支的保护状态取消,或者把自己的账号加入允许推送的名单。
3.3 SSH密钥配置与常见连接问题
“gitlab配置ssh密钥”也是高频问题。步骤本身不复杂,但细节容易出错。
生成密钥对:
ssh-keygen -t ed25519 -C "your_email@example.com"这里我推荐用Ed25519而不是RSA,因为Ed25519更短、更安全、性能更好。如果你的系统很老不支持Ed25519,再用RSA 4096。
查看公钥:
cat ~/.ssh/id_ed25519.pub复制输出内容,在GitLab的“用户设置”→“SSH密钥”页面粘贴,然后点击“添加密钥”。
测试连接:
ssh -T git@gitlab.yourdomain.com -p 2222如果返回“Welcome to GitLab, @username!”,说明配置成功。
常见问题排查:
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| Permission denied (publickey) | 公钥没添加或添加错误 | 重新复制公钥,确保没有换行和空格 |
| Connection refused | SSH端口不对 | 确认GitLab的SSH端口,默认是22,Docker部署通常是2222 |
| Host key verification failed | 首次连接未确认主机指纹 | 执行ssh-keyscan gitlab.yourdomain.com >> ~/.ssh/known_hosts |
| 仍然提示输入密码 | SSH代理未启动 | 执行eval $(ssh-agent -s)然后ssh-add ~/.ssh/id_ed25519 |
3.4 GitLab CI的入门配置与Runner注册
GitLab CI是GitLab的核心竞争力之一。配置CI只需要在仓库根目录放一个.gitlab-ci.yml文件:
stages: - build - test - deploy build-job: stage: build script: - echo "Building the project..." - make build artifacts: paths: - build/ test-job: stage: test script: - echo "Running tests..." - make test deploy-job: stage: deploy script: - echo "Deploying..." - ./deploy.sh only: - mainRunner的注册是CI能否跑起来的关键。在GitLab的“设置”→“CI/CD”→“Runners”页面获取注册令牌,然后在Runner机器上执行:
docker run -d --name gitlab-runner \ --restart always \ -v /srv/gitlab-runner/config:/etc/gitlab-runner \ -v /var/run/docker.sock:/var/run/docker.sock \ gitlab/gitlab-runner:latest docker exec -it gitlab-runner gitlab-runner register \ --non-interactive \ --executor "docker" \ --docker-image alpine:latest \ --url "https://gitlab.yourdomain.com/" \ --registration-token "<your-token>" \ --description "docker-runner" \ --tag-list "docker,linux" \ --run-untagged="true" \ --locked="false"注册完成后,在GitLab的Runners页面应该能看到一个绿色的在线Runner。
实操心得:GitLab CI的缓存机制很实用,但配置不当会导致缓存不命中。我建议在
.gitlab-ci.yml里显式指定缓存key,比如key: "$CI_COMMIT_REF_SLUG",这样不同分支的缓存互相隔离,不会互相覆盖。另外,缓存目录尽量放在项目目录内,不要用绝对路径,否则Runner迁移后会失效。
4. Gerrit部署与代码评审流程落地
4.1 Gerrit的安装环境准备
Gerrit是基于Java的,所以第一步是装JDK。推荐JDK 17,Gerrit 3.9之后的版本都要求JDK 17+:
sudo apt update sudo apt install -y openjdk-17-jdk java -version然后下载Gerrit的war包。截至2025年初,最新稳定版是3.10.x:
wget https://gerrit-releases.storage.googleapis.com/gerrit-3.10.0.warGerrit需要一个数据库来存储元数据。虽然它内置了H2数据库,但生产环境强烈推荐用PostgreSQL或MySQL。我用PostgreSQL:
sudo apt install -y postgresql sudo -u postgres createuser -P gerrit2 sudo -u postgres createdb -O gerrit2 reviewdb4.2 Gerrit初始化与配置文件详解
初始化Gerrit:
java -jar gerrit-3.10.0.war init --batch -d /home/gerrit/gerrit-site这个命令会交互式地问你一堆问题,--batch模式会用默认值。初始化完成后,配置文件在/home/gerrit/gerrit-site/etc/gerrit.config。
关键配置项:
[gerrit] basePath = git serverId = gerrit-server canonicalWebUrl = https://gerrit.yourdomain.com/ [database] type = postgresql hostname = localhost database = reviewdb username = gerrit2 [auth] type = HTTP [httpd] listenUrl = proxy-https://127.0.0.1:8081/ [sshd] listenAddress = *:29418 [container] javaOptions = "-Xmx2g"auth.type我设成了HTTP,配合Nginx做反向代理和认证。如果你不想折腾反向代理,可以用auth.type = DEVELOPMENT_BECOME_ANY_ACCOUNT,但这只适合测试环境,生产环境绝对不能用。
4.3 项目创建与权限模型配置
Gerrit的权限模型是它最强大的地方,也是最复杂的地方。权限配置在project.config文件里,通过Web界面或SSH命令修改。
创建项目:
ssh -p 29418 admin@gerrit.yourdomain.com gerrit create-project \ --parent All-Projects \ --require-change-id \ my-project--require-change-id这个参数很重要,它要求每个提交都包含Change-Id,这是Gerrit追踪评审记录的基础。Gerrit提供了一个commit-msg钩子来自动生成Change-Id:
git clone https://gerrit.yourdomain.com/my-project cd my-project curl -Lo .git/hooks/commit-msg https://gerrit.yourdomain.com/tools/hooks/commit-msg chmod +x .git/hooks/commit-msg权限配置的核心是refs/for/refs/heads/*的权限。默认情况下,只有项目所有者能直接推送,其他人只能推送到refs/for/main来创建评审。
一个典型的权限配置:
| 权限 | 适用引用 | 用户组 | 说明 |
|---|---|---|---|
| Label Code-Review | refs/for/refs/heads/* | Registered Users | 允许所有注册用户打分 |
| Label Verified | refs/for/refs/heads/* | CI Bot | 只有CI能打Verified标签 |
| Submit | refs/for/refs/heads/* | Project Owners | 只有项目所有者能合入 |
| Push | refs/heads/* | Project Owners | 直接推送权限 |
这套配置的效果是:普通开发者提交代码后,必须经过至少一个Code-Review +2和一个Verified +1才能合入。CI系统负责打Verified标签,人工负责打Code-Review标签。
4.4 Gerrit与CI系统的集成实践
Gerrit本身不包含CI功能,需要和Jenkins等CI系统配合。集成的核心是Gerrit Trigger插件。
在Jenkins里安装Gerrit Trigger插件后,配置Gerrit服务器连接:
- Gerrit Host:gerrit.yourdomain.com
- Gerrit SSH Port:29418
- Gerrit SSH Key:Jenkins的SSH私钥
- Gerrit User Name:jenkins
然后在Jenkins任务里配置触发器:
- 选择“Gerrit event”
- 添加“Patchset Created”事件
- 配置项目名称和分支
这样每次有人推送新的Patchset,Jenkins就会自动触发构建。构建成功后,Jenkins通过SSH命令给Gerrit打Verified标签:
ssh -p 29418 jenkins@gerrit.yourdomain.com gerrit review \ --verified +1 \ --message "Build succeeded" \ ${GERRIT_CHANGE_NUMBER},${GERRIT_PATCHSET_NUMBER}注意:Gerrit的评审流程和GitLab的MR流程有一个本质区别——Gerrit的每一次修改都是一个独立的Patchset,而不是在原提交上追加。这意味着你不能用
git commit --amend然后强推,而是要用git commit --amend后推送到同一个Change-Id。Gerrit会自动识别这是同一个Change的新Patchset。这个机制刚开始用会很不习惯,但习惯了之后会发现它让评审历史非常清晰。
5. 三款工具的问题排查与避坑指南
5.1 Gitea常见问题速查
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 推送大文件报413 | Nginx的client_max_body_size太小 | 调大到512M或更大 |
| SSH推送提示权限拒绝 | authorized_keys被覆盖 | 检查/home/git/.ssh/authorized_keys权限,确保是600 |
| Webhook不触发 | ROOT_URL配置错误 | 确保ROOT_URL和实际访问地址完全一致 |
| 头像不显示 | Gravatar被墙或DNS问题 | 在配置里关闭Gravatar,改用本地头像 |
| 数据库锁竞争 | 使用了SQLite | 迁移到PostgreSQL或MySQL |
| Actions任务卡住 | Runner未正确注册 | 检查runner日志,确认标签匹配 |
5.2 GitLab运维中的高频故障处理
“gitlab启动不了”是热词里经常出现的问题。根据我的经验,90%的启动失败都是以下几个原因:
内存不足:GitLab启动时如果内存不够,Puma会反复重启。查看/var/log/gitlab/puma/puma_stderr.log,如果看到“Cannot allocate memory”,就是内存问题。解决办法是降低worker数量或者加内存。
端口冲突:GitLab默认占用80和443端口。如果机器上已经有Nginx或Apache,就会冲突。解决办法是修改external_url里的端口,或者停掉冲突的服务。
数据库迁移失败:升级GitLab版本后,数据库迁移可能失败。查看/var/log/gitlab/gitlab-rails/database_migrations.log,根据错误信息处理。常见的是磁盘空间不足或数据库连接超时。
“gitlab 19只支持ubuntu 24.04”这个说法:这其实是一个误解。GitLab 19(如果指的是未来的大版本)目前还没有发布。GitLab的官方支持策略是,每个大版本会支持当时的主流LTS发行版。截至2025年初,GitLab 16.x支持Ubuntu 20.04和22.04。如果你看到类似的说法,建议直接查官方文档的“Supported Operating Systems”页面,不要轻信二手信息。
5.3 Gerrit部署中的典型坑点
Gerrit的坑主要集中在权限和评审流程上。
Change-Id缺失:如果提交时没有Change-Id,Gerrit会拒绝推送。解决办法是安装commit-msg钩子,前面已经说过。
权限配置不生效:Gerrit的权限有缓存,修改后需要刷新。执行ssh -p 29418 admin@gerrit gerrit flush-caches --cache projects可以强制刷新。
SSH连接被拒绝:Gerrit的SSH服务默认监听29418端口,不是22。连接时一定要指定端口:ssh -p 29418 user@gerrit。
评审无法合入:检查是否满足所有必要的标签。默认情况下,需要Code-Review +2和Verified +1。如果项目配置了额外的标签,也需要满足。
5.4 数据备份与恢复策略
不管用哪个工具,备份都是必须的。我分享一下我的备份策略。
Gitea备份:
# 二进制安装 sudo -u git /usr/local/bin/gitea dump -c /etc/gitea/app.ini # Docker安装 docker exec -u git gitea /usr/local/bin/gitea dump -c /data/gitea/conf/app.inidump命令会生成一个zip文件,包含数据库、仓库、配置和附件。恢复时解压到对应目录即可。
GitLab备份:
docker exec -t gitlab gitlab-backup create备份文件默认在/var/opt/gitlab/backups/目录。恢复时:
docker exec -it gitlab gitlab-backup restore BACKUP=<timestamp>注意:GitLab的备份不包含/etc/gitlab/gitlab.rb和/etc/gitlab/gitlab-secrets.json,这两个文件需要手动备份。
Gerrit备份:
Gerrit的备份相对简单,因为它的核心数据就是Git仓库和数据库。Git仓库直接打包git目录,数据库用pg_dump导出即可。
# 备份Git仓库 tar czf gerrit-git-$(date +%Y%m%d).tar.gz /home/gerrit/gerrit-site/git # 备份数据库 pg_dump -U gerrit2 reviewdb > gerrit-db-$(date +%Y%m%d).sql实操心得:备份一定要做恢复演练。我见过太多团队备份文件存了一大堆,真出事了发现恢复不了。建议每季度做一次恢复测试,在测试环境里把备份恢复一遍,确认流程没问题。另外,备份文件不要放在同一台机器上,至少同步到另一台服务器或对象存储里。
6. 从实际使用出发的选型建议
6.1 不同规模团队的选择路径
如果你是一个3-5人的小团队,我建议直接上Gitea。安装简单,维护成本低,功能完全够用。用Docker Compose跑起来,半小时就能搞定。省下来的时间用来写代码,比折腾GitLab的配置划算得多。
如果你是一个15-50人的团队,GitLab社区版是更合适的选择。它的CI/CD、代码评审、Issue跟踪、Wiki等功能可以覆盖团队的大部分协作需求。虽然资源消耗大一些,但换来的是完整的DevOps能力。一台8核16G的机器跑GitLab,再配一台4核8G的机器跑Runner,基本能满足日常需求。
如果你是一个对代码评审有严格要求的团队,比如做基础软件、做安全敏感项目,Gerrit值得考虑。它的评审流程虽然繁琐,但能确保每一行代码都经过审查。不过要做好心理准备,团队需要花时间适应Gerrit的工作流,初期效率可能会下降。
6.2 混合部署的可能性
其实这三个工具不是互斥的。我见过一些团队用Gitea做日常开发,用Gerrit做核心模块的评审。Gitea的仓库可以配置镜像推送到Gerrit,开发者在Gitea上提交,核心模块的变更自动同步到Gerrit走评审流程。
这种混合模式的好处是兼顾了开发效率和评审严谨性。但代价是维护两套系统,复杂度上升。适合有专职运维的中大型团队。
6.3 我个人的使用体会
我自己维护过Gitea和GitLab,Gerrit只是测试环境跑过。说几个真实的感受。
Gitea最让我满意的是它的“不折腾”。升级就是换个二进制文件,重启一下,完事。数据库用PostgreSQL,跑了两年没出过问题。Actions功能虽然不如GitLab CI强大,但跑个单元测试、构建个Docker镜像完全够用。
GitLab让我又爱又恨。功能确实全,但每次升级都提心吊胆,生怕哪个组件出问题。内存占用也是个大头,8G的机器跑起来紧巴巴的。不过它的CI/CD确实好用,.gitlab-ci.yml写起来很顺手,Runner的自动伸缩也很方便。
Gerrit的学习曲线确实陡。我第一次配权限的时候,对着文档研究了整整一个下午才搞明白refs/for/refs/heads/*是什么意思。但一旦跑起来,它的评审流程确实严谨,每一行代码的变更都有记录,谁在什么时候打了什么分,清清楚楚。
最后分享一个小技巧:不管你选哪个工具,都建议在正式迁移之前,先用测试环境跑一遍完整的流程——从代码提交到评审到合入到CI触发。把可能的问题提前暴露出来,比上线后手忙脚乱强得多。