新闻详情

新闻详情

首页 / 资讯中心 / 详情

2025年自建Git服务选型指南:Gitea、GitLab、Gerrit部署对比与实战

发布时间:2026/9/26 12:11:53来源:尧图网络
2025年自建Git服务选型指南:Gitea、GitLab、Gerrit部署对比与实战
1. 自建Git服务的选型逻辑与核心考量1.1 为什么2025年还要自建Git服务先说一个我自己的判断只要团队超过5个人代码托管这件事迟早要面对“自建还是用云端”的选择。云端服务省心但代码资产不在自己手里CI跑分钟数要花钱私有仓库成员数一超就得升级套餐。2025年这个时间点自建Git服务的性价比反而比前几年更高了——轻量方案成熟了容器化部署也标准化了一台4核8G的机器就能撑起一个几十人团队的日常开发。自建Git服务能解决的核心问题其实就三个代码资产的物理掌控、CI/CD流水线的完全自定义、与内部系统LDAP、Jira、制品库的深度集成。适合谁来参考我建议是这几类人中小团队的技术负责人、需要做代码审计的运维、想在自己机器上搭一套练手的开发者以及被云端服务账单刺痛过的创业者。Gitea、GitLab、Gerrit这三个名字经常被放在一起比较但它们其实不是同一类东西。Gitea是轻量级代码托管平台GitLab是全流程DevOps平台Gerrit是代码评审优先的Git服务器。选错了不是不能用而是会一直别扭。下面我把这三个方案从架构、资源占用、功能边界到部署实操全部拆开讲。1.2 三款方案的本质差异很多人把这三个当成“同类竞品”这是个误区。我用一句话概括它们的定位Gitea像“自建版的轻量GitHub”主打轻、快、够用Go语言写的单二进制文件就能跑。GitLab像“自建版的GitHubJenkinsJira合体”功能全但重Ruby on Rails起家现在核心组件用Go重写了不少。Gerrit像“代码评审的专用工具”Google出品每个提交都要经过评审才能合入适合对代码质量要求极高的团队。从资源占用上就能看出差异。我实测过一组数据同样是50个仓库、10个活跃用户方案内存占用空闲内存占用活跃磁盘占用基础启动时间Gitea约120MB约300MB约200MB3秒内GitLab约4GB约8GB约2GB2-5分钟Gerrit约800MB约1.5GB约500MB30秒左右这个表格不是让你背数字而是帮你建立直觉Gitea是“随手就能跑”GitLab是“得给它一台像样的机器”Gerrit是“介于两者之间但偏重评审”。1.3 选型决策树什么场景选什么我总结了一个简单的决策逻辑你可以直接对照团队小于20人只需要代码托管基本CI选Gitea。它的Actions功能已经能覆盖大部分CI需求而且资源占用低到可以和其他服务混部。团队20-200人需要完整的DevOps流水线、制品库、安全扫描选GitLab。它的功能完整度目前没有对手代价是资源消耗大。团队任何规模但代码评审流程极其严格比如嵌入式、金融、军工类项目选Gerrit。它的“每个提交必须评审”机制是硬约束不是可选项。还有一个容易被忽略的点迁移成本。Gitea和GitLab都支持从对方导入仓库Gerrit的迁移相对麻烦一些。如果你现在用的是云端服务想迁到自建Gitea和GitLab的导入工具都很成熟Gerrit需要额外做提交历史的映射。2. Gitea部署实践轻量但不简陋2.1 为什么我首选Docker Compose部署GiteaGitea的部署方式很多二进制、包管理器、Docker都有。我试过在Ubuntu上用apt装也试过直接下二进制跑最后长期用的是Docker Compose。原因很简单升级和备份都太方便了。二进制升级要停服务、换文件、改权限Docker Compose只需要改一下镜像tag然后docker compose up -d。先给一个我实际在用的compose文件你可以直接抄version: 3 services: gitea: image: gitea/gitea:1.22 container_name: gitea environment: - USER_UID1000 - USER_GID1000 - GITEA__database__DB_TYPEpostgres - GITEA__database__HOSTdb:5432 - GITEA__database__NAMEgitea - GITEA__database__USERgitea - GITEA__database__PASSWDgitea_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:15 container_name: gitea_db restart: always environment: - POSTGRES_USERgitea - POSTGRES_PASSWORDgitea_password - POSTGRES_DBgitea volumes: - ./postgres:/var/lib/postgresql/data这里有几个我踩过坑的地方要说明。第一数据库别用SQLite。SQLite在单用户场景下没问题但一旦有并发操作比如多人同时push锁竞争会让你怀疑人生。PostgreSQL是Gitea官方推荐的生产级选择。第二SSH端口别用22。宿主机上的22通常已经被sshd占了映射到222是个好习惯后面配置SSH克隆地址时记得改。第三时区挂载别省。不挂时区的话提交时间会显示成UTC看日志的时候很别扭。2.2 首次启动后的关键配置容器起来之后浏览器打开http://你的IP:3000会看到初始化页面。这里有几个选项直接影响后续使用体验数据库设置部分如果你用了上面的compose直接选PostgreSQL主机填db:5432用户和密码填compose里设的。注意这里的“主机”要填容器名db不是localhost因为Gitea和Postgres在两个容器里。应用基本设置里SSH服务端口要改成222对应compose里的映射Gitea基础URL填你最终访问的地址比如http://git.yourdomain.com:3000。这个URL后面改起来麻烦最好一次填对。管理员账号建议在初始化页面就创建别跳过。跳过之后虽然可以进容器用命令行创建但多一步麻烦。初始化完成后我建议立刻做三件事关闭注册。在管理后台 - 用户设置里把“允许用户自助注册”关掉改成管理员手动创建。自建服务暴露在公网的话开放注册就是给自己找麻烦。配置SSH密钥。每个用户在设置 - SSH/GPG密钥里添加自己的公钥。Gitea支持RSA和Ed25519我推荐Ed25519更短更安全。建组织而不是建个人仓库。团队协作场景下仓库应该属于组织Organization而不是某个人的账号。这样人员变动时仓库不会跟着走。2.3 Gitea的合并指定合并人技巧热词里有个“gitea 合并指定合并人”这个需求在实际协作中很常见。Gitea本身没有“强制指定合并人”的硬约束但可以通过分支保护规则来实现类似效果。具体操作路径是进入仓库 -设置-分支- 添加保护规则。在规则里勾选“启用合并白名单”然后把你信任的合并人加进去。这样只有白名单里的人才能点合并按钮其他人只能提PR。如果你想要更严格的“必须由某人合并”Gitea目前不支持按PR指定合并人。我的做法是配合CODEOWNERS文件在仓库根目录建一个.gitea/CODEOWNERS注意Gitea的路径和GitHub不同内容格式是*.go zhangsan /docs/ lisi这样当PR修改了对应文件时Gitea会自动请求对应的owner来review。虽然不是强制合并但至少能起到提醒作用。2.4 Gitea的备份与恢复自建服务最怕的就是数据丢。Gitea的备份其实很简单因为所有数据都在./gitea和./postgres两个目录里。我的做法是写一个cron脚本每天凌晨3点执行#!/bin/bash BACKUP_DIR/backup/gitea/$(date %Y%m%d) mkdir -p $BACKUP_DIR docker exec gitea_db pg_dump -U gitea gitea $BACKUP_DIR/gitea.sql tar -czf $BACKUP_DIR/gitea-data.tar.gz -C /path/to/compose/gitea . find /backup/gitea -type d -mtime 7 -exec rm -rf {} \;这个脚本做了三件事导出数据库、打包data目录、删除7天前的备份。恢复的时候先起一个空的Postgres导入sql再把data目录解压回去最后起Gitea容器。注意备份脚本一定要实际测试恢复流程。我见过太多人备份跑了半年真出事的时候发现恢复不了原因是备份文件权限不对或者数据库版本不匹配。3. GitLab部署实践重但值得3.1 GitLab社区版Docker部署的资源规划GitLab是这三个方案里最吃资源的。官方推荐至少4核8G我实测下来4核8G是底线8核16G才舒服。如果你用Docker部署内存占用会更高一些因为容器本身有开销。先给compose文件version: 3.6 services: gitlab: image: gitlab/gitlab-ce:16.11.0-ce.0 container_name: gitlab restart: always hostname: git.yourdomain.com environment: GITLAB_OMNIBUS_CONFIG: | external_url http://git.yourdomain.com gitlab_rails[gitlab_shell_ssh_port] 2222 gitlab_rails[time_zone] Asia/Shanghai puma[worker_processes] 2 sidekiq[max_concurrency] 10 postgresql[shared_buffers] 512MB prometheus_monitoring[enable] false 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默认是根据CPU核数自动算的4核机器上会开4个worker每个占几百MB内存。改成2能省不少内存。sidekiq max_concurrency默认是25对中小团队来说10就够了。prometheus_monitoring默认开启会额外占1GB左右内存如果不需要监控数据直接关掉。shm_size这个参数很多人会忽略。GitLab的Postgres需要共享内存默认Docker给的64MB不够会导致数据库启动失败。设成256MB比较稳妥。3.2 GitLab首次启动与中文配置GitLab首次启动特别慢因为要初始化数据库、编译资源。在4核8G的机器上大概需要5-8分钟。这段时间docker logs -f gitlab会刷很多日志看到gitlab Reconfigured!就说明好了。首次访问会要求设置root密码。设置完之后登录第一件事是改语言为中文。路径是右上角头像 -Preferences-Localization-Language选“简体中文” - 保存。刷新页面就变中文了。然后建议做这几个配置关闭注册管理中心 - 设置 - 通用 - 注册限制取消“启用注册”。配置SSH端口如果你改了SSH映射端口要在管理中心 - 设置 - 通用 - GitLab Shell里把SSH端口改成2222否则克隆地址会显示错误的端口。调整备份保留管理中心 - 设置 - 备份设置备份保留时间为7天避免磁盘被备份撑满。3.3 GitLab导入项目的几种方式热词里“gitlab导入项目”出现频率很高我分场景说。从其他GitLab实例导入在新建项目 - 导入项目 - GitLab里填源实例的URL和访问令牌。这里有个坑如果源实例是自签证书导入会失败报login failed. check api token or gitlab version。解决办法是在目标实例的/etc/gitlab/gitlab.rb里加一行gitlab_rails[import_url_allowlist]或者临时关闭SSL验证。从GitHub导入类似路径需要GitHub的personal access token。注意token的权限要勾选repo。从本地已有仓库上传这是最常见的需求。步骤是cd existing_repo git remote add origin http://git.yourdomain.com/group/project.git git push -u origin --all git push -u origin --tags如果仓库很大push的时候可能会超时。GitLab默认的push大小限制是5GB一般够用。如果还是失败检查一下nginx的client_max_body_size配置。从Gitea迁移到GitLabGitea的仓库可以直接用“通过URL导入”的方式填Gitea的克隆地址GitLab会拉取所有分支和标签。但issue和PR不会跟着过来需要手动迁移。3.4 GitLab CI的入门配置GitLab CI是它相比Gitea最大的优势之一。配置就是在仓库根目录放一个.gitlab-ci.yml文件。给一个Go项目的例子stages: - test - build variables: GO_VERSION: 1.22 test: stage: test image: golang:${GO_VERSION} script: - go mod download - go test ./... -v only: - merge_requests - main build: stage: build image: golang:${GO_VERSION} script: - go build -o app ./cmd/app artifacts: paths: - app expire_in: 7 days only: - main这个配置做了两件事MR和main分支上跑测试main分支上构建产物并保留7天。artifacts这个功能很实用构建出来的二进制可以直接在GitLab界面下载。要跑CI你需要一个Runner。GitLab 16之后Runner的注册方式改成了用认证令牌。在管理中心 - CI/CD - Runner里新建一个Runner拿到令牌后在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 \ --url http://git.yourdomain.com \ --token 你的令牌 \ --executor docker \ --docker-image alpine:latest--executor docker意味着每个job都在一个干净的容器里跑隔离性好但每次要拉镜像。如果网络慢可以改成shell执行器但隔离性差一些。3.5 GitLab内存占用过多的排查“docker gitlab 占用内存过多”是个高频问题。我遇到过几次排查思路是这样的先用docker stats gitlab看实时内存。如果超过8GB基本可以确定是某个组件失控了。进容器用gitlab-ctl status看各服务状态重点看puma、sidekiq、postgresql。最常见的元凶是sidekiq。它处理后台任务如果积压了大量任务比如有人一次性push了几百个提交触发了几百个pipeline内存会飙升。解决办法是限制并发在gitlab.rb里设sidekiq[max_concurrency] 5然后gitlab-ctl reconfigure。第二个常见原因是prometheus。它默认开启会持续采集指标内存占用不低。如果不需要直接prometheus_monitoring[enable] false。第三个是Postgres的shared_buffers。默认值可能偏大4核8G的机器上设512MB比较合适。如果调完还是高可以考虑把GitLab拆成多容器部署把Postgres和Redis独立出来。但这样运维复杂度会上升中小团队不太建议。4. Gerrit部署实践评审优先的另一种思路4.1 Gerrit的适用场景再确认在讲部署之前我想再强调一下Gerrit的定位。它不是“另一个GitLab”它的核心机制是每个提交都必须经过Code Review才能合入。这意味着你不能直接push到main分支只能push到refs/for/main然后Gerrit会创建一个评审任务。这个机制适合什么场景我总结了几类需要严格审计的代码库、多人协作且质量要求高的项目、需要记录每次变更评审意见的团队。如果你只是想要一个代码托管Gerrit会让你觉得处处受限。4.2 Docker部署Gerrit的完整流程Gerrit官方有Docker镜像但配置起来比Gitea和GitLab麻烦一些。先给composeversion: 3 services: gerrit: image: gerritcodereview/gerrit:3.9.0 container_name: gerrit restart: always ports: - 8080:8080 - 29418:29418 volumes: - ./git:/var/gerrit/git - ./index:/var/gerrit/index - ./cache:/var/gerrit/cache - ./etc:/var/gerrit/etc environment: - CANONICAL_WEB_URLhttp://your-ip:8080首次启动后Gerrit会在./etc目录下生成配置文件。你需要编辑gerrit.config关键配置项[gerrit] basePath git canonicalWebUrl http://your-ip:8080 [database] type h2 database /var/gerrit/db/ReviewDB [auth] type HTTP [httpd] listenUrl http://*:8080/ [sshd] listenAddress *:29418auth.type这里我填的是HTTP适合内网环境。如果要对接LDAP改成ldap并配置server和accountBase。生产环境建议用OAUTH或LDAP别用DEVELOPMENT_BECOME_ANY_ACCOUNT。配置改完后重启容器docker restart gerrit。4.3 Gerrit的SSH密钥与首次提交Gerrit的SSH端口是29418。添加公钥的方式和Gitea不同需要在Web界面登录后进Settings - SSH Keys添加。注意Gerrit的Web登录依赖auth.type的配置如果是HTTP类型需要配合反向代理做认证。添加完密钥后测试连接ssh -p 29418 your-usernameyour-ip gerrit version如果返回版本号说明SSH配置成功。首次提交代码的流程和普通Git不同git clone ssh://your-usernameyour-ip:29418/project-name cd project-name # 修改代码 git add . git commit -m feat: add new feature git push origin HEAD:refs/for/main注意最后push的目标是refs/for/main不是main。push成功后Gerrit会返回一个评审链接你可以在Web界面看到这次提交并邀请其他人review。4.4 Gerrit的评审流程与权限配置Gerrit的权限模型比Gitea和GitLab复杂得多。核心概念是refs上的权限。比如refs/heads/*上的Push权限控制谁能直接推送到分支refs/for/*上的Push权限控制谁能创建评审。默认情况下Registered Users组有refs/for/*的push权限但没有refs/heads/*的push权限。这意味着普通用户只能提评审不能直接合入。管理员可以通过All-Projects - Access来调整。一个常见的配置需求是允许特定人员直接push到main分支比如紧急修复。操作路径是All-Projects - Access - Edit在refs/heads/main上添加Push权限然后把人加进去。但我不建议这么做因为一旦开了口子评审机制就形同虚设了。Gerrit的评审打分是-2到2。2表示同意合入-2表示否决。通常需要至少一个2才能合入这个规则可以在Access里配置Label: Code-Review的Submit权限。5. 三方案横向对比与常见问题排查5.1 功能与运维成本对比表前面分开讲了三个方案的部署这里给一个横向对比方便你做最终决策维度GiteaGitLabGerrit代码托管支持支持支持PR/MR支持支持评审机制CI/CD内置Actions内置CI功能最强需外接Jenkins制品库基础支持完整支持不支持代码搜索基础高级基础权限模型简单中等复杂学习曲线低中高运维成本低高中社区活跃度高极高中从这张表能看出来Gitea是“够用就好”GitLab是“什么都有”Gerrit是“评审专用”。没有绝对的好坏只有适不适合。5.2 常见问题速查表我把实际运维中遇到的问题整理成表格方便你快速定位问题现象可能原因解决方向Gitea SSH克隆失败SSH端口未改或防火墙拦截检查compose端口映射和防火墙规则GitLab启动不了内存不足或shm_size太小加到8G内存shm_size设256mGitLab 502错误puma worker崩溃看gitlab-ctl tail puma日志调低worker数Gerrit push被拒目标分支写错确认push到refs/for/分支名GitLab导入报token错误源实例证书问题检查SSL或临时关闭验证Gitea合并按钮灰色分支保护规则限制检查白名单和CI状态GitLab备份文件过大备份保留了太多历史调整备份保留天数Gerrit Web登录失败auth.type配置错误检查gerrit.config的auth段5.3 我踩过的几个坑第一个坑是GitLab的SSH端口。我一开始用默认的22结果和宿主机的sshd冲突容器起不来。后来改成2222但忘了在gitlab.rb里改gitlab_shell_ssh_port导致克隆地址显示的还是22怎么都连不上。这个配置项在Web界面改不了必须改配置文件然后reconfigure。第二个坑是Gitea的数据库迁移。我一开始用SQLite后来想换PostgreSQL直接改配置发现数据没了。正确做法是先用gitea dump导出再改配置再导入。或者干脆重新初始化把仓库从本地重新push一遍。第三个坑是Gerrit的首次push。我习惯性地git push origin main结果被拒绝报错信息也不直观。后来才明白Gerrit的评审机制要求push到refs/for/main。这个设计对新手很不友好但理解了之后会觉得合理。第四个坑是GitLab CI的Runner注册。GitLab 16之后注册方式变了网上很多老教程还在用registration token但新版本已经改成authentication token了。我照着老教程操作了半天一直报错后来看官方文档才发现变了。5.4 安全加固的几条建议自建服务暴露在公网的话安全加固不能省。我总结了几条必做的强制HTTPS。用Lets Encrypt或者自签证书都行但别用HTTP传代码。GitLab和Gitea都支持配置证书Gerrit需要配合反向代理。关闭自助注册。三个方案都支持关闭注册只允许管理员创建账号。配置防火墙。只开放必要的端口SSH端口建议改成非标准端口减少扫描。定期更新。这三个项目都有活跃的安全更新尤其是GitLab高危漏洞修复要及时跟进。备份加密。备份文件里包含所有代码和配置建议加密存储。提示GitLab的高危漏洞修复通常会在安全公告里给出补丁版本看到公告后尽快升级。升级前先备份升级后验证核心功能。6. 我的最终选型建议如果你看到这里还在纠结我给你一个更直接的判断先问自己一个问题——你的团队有没有专职运维有选GitLab功能全运维能扛住。没有选Gitea一个人就能维护出问题也好排查。Gerrit是个特例只有当你明确需要“强制评审”这个机制时才选它否则它的学习成本会让你后悔。我自己的团队用的是GiteaDrone的组合Gitea管代码Drone管CI。这个组合的资源占用比GitLab低一个数量级功能上覆盖了我们90%的需求。剩下10%的需求比如制品库我们用MinIO单独解决。这种“拼装”思路适合小团队灵活且可控。最后分享一个小技巧不管你选哪个方案先把备份和恢复流程跑通再往里放代码。我见过太多人兴冲冲部署完就开始用结果某天磁盘满了或者容器崩了才发现备份没配。自建服务的核心价值是“掌控”但掌控的前提是你真的能掌控——包括数据的安全。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

羽毛球目标检测数据集:3580张实拍+拼接图,VOC+YOLO双格式 2026/9/27 1:42:28

羽毛球目标检测数据集:3580张实拍+拼接图,VOC+YOLO双格式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
C语言循环练习题精讲:从累加累乘到图形打印与字符串处理 2026/9/27 1:42:28

C语言循环练习题精讲:从累加累乘到图形打印与字符串处理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
ZYNQ7020 JTAG烧写失败排查与最小启动实践 2026/9/27 1:42:28

ZYNQ7020 JTAG烧写失败排查与最小启动实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
图盲去模糊实战:从图拉普拉斯正则到代码复现的完整路径 2026/9/27 1:42:28

图盲去模糊实战:从图拉普拉斯正则到代码复现的完整路径

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
树莓派SD卡/U盘格式化故障底层原理与精准修复 2026/9/27 1:42:27

树莓派SD卡/U盘格式化故障底层原理与精准修复

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
MATLAB扩频通信系统仿真:DSSS与FHSS从链路搭建到误码率分析 2026/9/27 1:42:21

MATLAB扩频通信系统仿真:DSSS与FHSS从链路搭建到误码率分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉