news 2026/9/6 12:20:27

GitLab vs Gitea:代码托管选型指南与踩坑经验

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GitLab vs Gitea:代码托管选型指南与踩坑经验

我们组之前在代码托管工具上踩了不少坑,从最早的 SVN 迁移到 Git 之后,一直在纠结用 GitLab 还是轻量级的 Gitea/Gogs。团队人数从 5 个人涨到了 40 多个人,中间换过一次方案,所以对这个问题的体会特别深。

这篇文章我不打算跟你罗列官方文档上的功能对比表,那样太没意思了。我更想从一个实际带团队、每天要处理代码托管、CI/CD、权限管理这些破事的人的角度,聊聊这两个方案到底差在哪,什么情况下选哪个,以及你在部署和使用过程中一定会遇到的那些“坑”。

先说结论:没有绝对更好的方案,只有当前阶段更合适的方案。如果你的团队是 10 人以内、想要极速搭建、维护省心,轻量级方案(Gitea 或 Gogs)绝对够用;但如果团队超过 20 人,或者对代码安全、权限审计、内网隔离、CI/CD 集成有比较严苛的要求,那 GitLab 的完整生态会让你省掉很多麻烦。下面我拆开来说。

1. 两个选择的核心逻辑:它们根本不是一类东西

1.1 GitLab 定位:一站式 DevOps 平台

GitLab 已经不只是一个 Git 托管工具了,它是一个完整的 DevOps 生命周期管理平台——从代码托管、代码审查、Issue 追踪、Wiki,到内置的 CI/CD、容器镜像仓库、安全扫描、监控,全都有。意味着你可以在一个系统里完成“提交代码 -> 跑测试 -> 构建镜像 -> 部署到服务器 -> 验证”的完整闭环。

这带来的最大好处是,你的团队不需要在 Jenkins、SonarQube、Harbor、Jira 之间来回切换,GitLab 自己就能把这些活全部包圆了。尤其是 CI/CD,用.gitlab-ci.yml一个文件搞定,和代码放一起,天然的 GitOps 思路,比单独维护一套 Jenkins 舒服太多了。

但是,功能全的代价就是重。GitLab 是 Ruby on Rails 写的,底层依赖 PostgreSQL、Redis、Gitaly、Sidekiq 等一堆组件,生产环境部署至少要 4C8G 的机器才能勉强跑得很舒服,官方推荐 8C16G。内存动不动就吃 2-3G,启动服务慢、吃资源,用起来有种“杀鸡用牛刀”的感觉,如果只是单纯托管代码,这个成本实在是有点高。

1.2 轻量级方案(Gitea/Gogs)定位:极简代码托管

Gitea 和 Gogs 走的是完全相反的路线——用 Go 语言写的,编译完就是一个二进制文件,加上配置文件和数据库,完事了。内存占用只有几十 MB,跑在树莓派或者 1C1G 的云主机上毫无压力。部署过程最快可以在 5 分钟内结束(下载二进制、初始化数据库,完事)。这个量级,拿它做个人代码备份、小团队内部协作托管的体验是真心爽。

Gitea 是 Gogs 的一个社区分支演化出来的,目前活跃度比 Gogs 高得多,功能也更丰富(内置了 Action、Package Registry),所以如果选轻量级方案,我建议优先 Gitea。但无论 Gitea 还是 Gogs,它就是一个“Git 仓库托管”工具,重心在仓库管理和轻量协作,CI/CD 这块虽然也在补课,但和 GitLab 的成熟度不在一个量级。

1.3 两者本质区别:定位不同,适用场景不同

用生活化的类比:

  • GitLab 像一个自带食堂、保安、健身房的大型写字楼,什么都有,但你得付高昂的物业费(资源、维护、学习成本)。
  • Gitea 像一个共享办公工位,桌子和椅子都有,核心需求解决得很好,茶水间也可能配了,但你指望楼里有个完整的健身中心,那就为难它了。

所以,你的团队到底是要一栋“写字楼”还是一个“工位”,取决于你的团队规模和业务复杂程度。下面是两个方案的关键差异对照表:

维度GitLabGitea / Gogs
内存占用2GB 起步,推荐 8GB+几十 MB 到 256MB
部署难度高(依赖组件多,易出问题)极低(单文件部署)
CI/CD内置,非常成熟基础版(Gitea 有 Action,但生态较弱)
代码审查MR 流程完善,支持权限分级基础 PR/MR 功能,够用但简单
资源消耗极低
扩展性企业级,支持大规模团队适合小团队/个人
维护成本高(升级、备份、灾备都要考虑)低(升级就是一个二进制替换)
适合规模20 人以上 / 严肃 DevOps1-20 人或轻量使用

这个表的背后,考验的是你对“团队现状”的判断力——你的痛点到底是缺一个“能放代码的地方”,还是缺一套“持续交付的规范体系”。想清楚这一点,选型就完成了一大半。

2. 资源消耗与部署门槛:一次实打实的部署对比

2.1 部署 GitLab 的真实体验

我最早用 Docker Compose 部署 GitLab,本以为一个docker-compose.yml就能搞定,结果远远没我想的那么简单。GitLab 官方镜像gitlab/gitlab-ce至少 2GB,下载就要等半天;起来之后 CPU 一直飙高,因为它在后台做初始化。你挂着docker logs看日志,一堆初始化任务排队跑,等几分钟到十几分钟是很正常的。

说一下我当时踩的坑。GitLab 默认端口用的是 80 和 443,如果宿主机上已经有 Nginx 或者别的 Web 服务,端口冲突就来了。你必须用external_url指定一个别的端口,比如http://192.168.1.100:8080,然后在容器里映射8080:808443:443。这个external_url很关键,不只是访问地址的问题,你会看到仓库的克隆 URL 都基于它生成。

还有那个经典的gitlab.rb配置文件。改完配置文件,你以为重启就完事了?不,你要执行gitlab-ctl reconfigure,这个过程会重新生配置并重启一系列内部组件,等个几分钟很正常。有次我等得无聊,多执行了一次 reconfigure,结果和正在跑的升级任务撞车,直接报错,最后只能进容器手动清理锁文件,那次是真的被折腾得不轻。

2.2 部署 Gitea 的魔法体验

反观 Gitea,部署体验可以用“魔法”来形容。我用的 Docker 方式,docker-compose.yml里定义两个服务:serverdb(用 SQLite 的话,连 db 都可以省)。image: gitea/gitea:latest,映射端口,挂载一个数据卷,docker-compose up -d,浏览器一打开就能看到安装页面,填写仓库名称、数据库信息、管理员账号,前后也就是两三分钟。

如果不用 Docker,甚至你只需要下载那个 100MB 左右的二进制文件,扔到/usr/local/bin,配 systemd 服务,二进制直接跑起来。数据库可以用 SQLite,就是一个文件,备份直接把目录打包完事。这种简单的体质对中小团队来说太友好了。

2.3 资源账单对照

  • GitLab:部署 4C8G 服务器,跑起来稳定占用空闲内存 2.5GB 左右,一有 CI 任务并发跑,CPU 和内存曲线直接起飞。官方建议的配置是 8C16G,如果你要在上面跑生产级 CI 流水线,那这台机器就不能干别的了。
  • Gitea:1C1G 的服务器就能带得动 20 人小团队,内存常驻大概 100MB 上下,你可以把同一台机器上还跑着 Nginx、MySQL 这些别的服务。

我见过很多小团队可能就一台 4G 内存的服务器,既跑 Nginx 又要挂几个内部系统,硬上 GitLab,没过多久磁盘 IO 先报警,GitLab 自身动不动就 502(Unicorn/Gitaly 扛不住),最后只能迁移到轻量方案。所以如果你手头资源有限,轻量级方案是非常理性的选择。

3. 日常使用体感:命令、权限和那些你一定会踩的坑

3.1 配置 SSH 密钥与 Token

不管用哪个方案,你要提交代码到远程仓库,最常用的方式就是 SSH 密钥。在 GitLab 和 Gitea 里配置 SSH Key 的逻辑基本一样:在用户设置里找到 SSH Keys,把你本地的~/.ssh/id_rsa.pub内容粘进去,保存。

但有一点很多新手会踩坑:你本机如果之前用过 GitHub,已经有了 SSH Key,这个 Key 是可以复用的,不必重新生成。只要把同一个公钥加到 GitLab/Gitea 的 SSH Keys 设置里就行。如果你发现 SSH 连接不上,排查顺序一般是:

  1. 确认公钥是否已经添加到 Web 页面里(不是私钥!),很多新手容易复制只读权限的私钥内容。
  2. 确认你的 SSH 私钥文件是否存在,且权限是 600(chmod 600 ~/.ssh/id_rsa)。
  3. 确认仓库地址用的是 SSH 格式(git@gitlab.example.com:group/project.git),而不是 HTTPS。

另外,GitLab 的 Token 机制也经常让人一头雾水。新版 GitLab 越来越强调用 Personal Access Token 替代密码——尤其是进行 API 调用或者备用 HTTP 方式时。有些人会遇到“login failed. check api token or gitlab version”这种报错,多半是 Token 失效(做过密码重置会导致所有 Token 自动失效),或者 Token 的 scope 权限不足(至少要勾选apiread_repositorywrite_repository),也可能你用高版本 GitLab 配了 v1 API 地址,走了已废弃的 v3 通道,导致认证失败。弄一个尽量新一点的 Token,权限全部先勾上,基本能绕过 90% 的登录怪问题。

3.2 从 GitLab 拉取代码到本地的正确姿势

拉取代码这个操作看起来简单,git clone而已,但有几个细节在团队内部经常引发混乱。一是分支权限:默认每个开发者只有main分支的读权限,如果你想限制某人只能看某些 branch 或 tag,GitLab 有比较细粒度的 Protected Branches 控制;Gitea 也有类似保护分支功能,但配置项和组合方式要简单不少。

二是 clone 时的用户身份:如果一时糊涂用了公司的账号邮箱提交,代码历史里就会留下一条错误记录。建议在团队初始化时统一约定提交信息格式,比如在 GitLab/Gitea 后台开启“阻止未验证邮箱提交”或“强制 GPG 签名”的规则,能省掉后面不少麻烦。

三是 GitLab 默认端口问题。很多小团队会用 Docker 映射一个非 80 端口,比如 8929,那 HTTP clone 地址就会变成http://192.168.1.100:8929/group/project.git,没问题。但如果你的防火墙把 8929 封了,拉取代码就会直接卡住。检查端口时,不要只看 TCP 通不通,GitLab 的gitlab.rb里如果设置了nginx['listen_port'],和 Docker 端口映射不一致,也会出现网页能打开、clone 却连不上的诡异情况。

3.3 网页端操作细节

Gitea 的 Web 界面非常轻,打开项目、看文件、编辑、提交 MR,响应都很快。GitLab 的页面功能丰富,但有时一个页面加载好多次请求,网络稍差一点就会转圈。特别是在内网用 HTTP 明文访问 GitLab 时,有些浏览器会拦截敏感操作,导致像上传文件、内嵌编辑这样的小功能时不时抽风。

关于登录还有一个坑:GitLab 有时会遇到“422 登录错误”或者“登录后立刻跳回登录页”。很多时候你在隐身模式或换浏览器能登录,是因为缓存了过期的 CSRF Token 或者 cookie 被篡改了。遇到这种情况,清掉当前站点的 cookie,或者直接隐身模式登录,多半能解决。如果你换隐身也登不上,再检查是不是设置了外部统一登录(LDAP/SSO),跳转链路里的回调 URL 没配置正确,也会出现反复回到登录页的死循环。

3.4 权限模型差异

GitLab 的权限模型分得非常细:Guest、Reporter、Developer、Maintainer、Owner 五级,还可以结合 Group 进行嵌套管理。这在 30 人以上的团队里价值很大——可以精确控制一个测试同学只有 issue 的查看权限,开发同学只有自己项目的推送权限,管理员才能管理 runner。

Gitea 的权限模型要简单得多:读、写、管理,四个字基本就没有了。它也有 “Team” 概念,但颗粒度比 GitLab 要粗。对于 10 人小团队来说,这个简单模型完全够用;但对需要严格权限审计、不同组不同规范的团队来说,你可能就得花额外的精力去手动管理仓库归属,而不是靠系统权限分层。

4. CI/CD、代码审查与扩展生态:这是分水岭

4.1 CI/CD 是最大的分水岭

如果你的团队要正经跑 CI/CD,选 GitLab 的优势就很明显了。

在 GitLab 里,你在项目根目录放一个.gitlab-ci.yml文件,里面定义 stages(build、test、deploy 等)和 job,然后配置一个 GitLab Runner。Runner 可以是独立的服务器或容器,也可以是用 Docker 动态创建的。每次代码 push 到分支,GitLab 就会自动触发 Runner 跑对应 job。这个过程不需要第三方的 Jenkins、Travis CI,GitLab 自己就是控制面核执行面。

.gitlab-ci.yml里支持极其丰富的玩法:rules条件判断、artifacts产物传递、environment部署环境、needs任务依赖、cache缓存加速。你甚至可以定义多环境(staging、production),一键部署。这个能力对于中小团队来说,是降维打击式的方便——你不需要单独维护一套 CI 系统,也不用花大精力学习 Jenkins 的 Pipeline 语法。

Gitea 也内置了 Gitea Actions(和 GitHub Actions 语法基本一致),可以跑简单的 CI 任务,比如执行构建命令、跑测试。但它没有真正的 CD 能力——比如把 artifact 推送到 Kubernetes 或者 SSH 到远程服务器执行自动化部署,这一块需要你自己写脚本或者集成第三方工具。如果你只是需要“push 之后自动跑一下 go test”,Gitea Actions 够用;但如果你想搞完整的持续部署流程,还是得在 GitLab 和独立 CI 系统之间二选一。

4.2 代码审查与 MR 流程

代码审查这块,GitLab 的 Merge Request 流程非常成熟。你可以设置 approvals(审批规则),要求代码必须经过至少一个 maintainer 的 approve 才能合入;可以配置合并前必须有通过的 CI 任务;还可以设置合入分支后自动删除源分支。这些规则组合起来,能形成一套比较严苛的团队协作规范。

Gitea 的 Pull Request 功能有基础版:创建 PR、评论、同意/拒绝合并、冲突检测。但对于 “谁能 approve”、“CI 没过就不能合并”、“合并策略(squash/merge/rebase)” 这些规则,Gitea 的设置要简陋一些。也许这正合小团队的胃口,因为规则太多反而拖慢节奏。但当你们开始计较 “谁签的 code review 才算数” 的时候,就该往 GitLab 的审批流走了。

4.3 插件与集成生态

GitLab 的生态包括各种 API、Webhook、Kubernetes 集成、Terraform 支持、安全扫描(SAST/DAST)、License 合规检查等等。这意味着它在企业级研发流程里能发挥的空间非常大。比如你可以把 GitLab 的groups和 LDAP 组织架构对齐,员工入职/离职自动同步权限;可以接入 Slack/飞书做通知推送。

Gitea 也有 Webhook,可以对接飞书、钉钉、Discord、Slack,基本的通知能力是有的。但是企业级、体系化的东西——比如统一的审计日志、SCIM 用户管理、合规扫描、全链路 trace 等——就基本为零了。这就是轻量级的代价。

5. 备份、升级和日常维护经验

5.1 备份策略

GitLab 的备份必须用官方工具gitlab-backup create(老版本是gitlab-rake gitlab:backup:create),它会备份 PostgreSQL 数据库、Git 仓库、附件的文件,输出一个 tar 包。另外你还要备份gitlab.rb/etc/gitlab/gitlab-secrets.json。这个 secrets 文件是加密密钥,丢了它,备份的数据库也解不开,那时候才真是欲哭无泪——有次我 restore 备份时报无权限,检查一圈发现是备份目录属主不对,chown之后才能正常 restore。所以说,备份不只是打包,还要定期做一次真实的恢复演练,否则备份在那里你也不知道它能不能用。

Gitea 的备份就简单多了。用 SQLite 数据库时,核心就是备份一个.db文件加custom/目录(包含 keys、avatar、附件),用gitea dump命令可以生成一个压缩包。你要是用 Docker,也可以直接把挂载的 volume 目录整个 tar 走。恢复的时候把文件放回去重启服务即可。这种“复制粘贴式备份”对运维压力小很多。

5.2 升级与版本管理

GitLab 升级是个技术活。大版本升级不能跳版本,要沿着 16.0 -> 16.1 -> 16.2 这样逐步升,每次升完要先跑gitlab-ctl reconfigure和 migration,这一步慢了可能要十几分钟。Docker 方式升级就是换 tag、重新 build,但底层数据库迁移逻辑还是那个流程。没有时间规划直接跳级升级,很容易碰上数据库迁移报错,最后只能 restore 备份重来。

Gitea 升级就太轻松了。官方提供了gitea dump备份,然后新版本二进制替换旧版本,跑一次gitea migrate,完事。整个过程如果仓库不多,一分钟以内就能结束。你要是用 Docker,docker-compose pull && docker-compose up -d两行命令搞定。这对平时忙不过来的小团队来说,幸福感不是一个量级的。

5.3 磁盘扩容与备份周期

还有一点容易被忽视:GitLab 的仓库数据量增长非常快,尤其是你们开始跑 CI,构建产物都放在本机builds目录或 artifacts 里,磁盘不够了就各种离奇报错。建议给 GitLab 挂一个独立数据盘,并且针对 artifacts 设置过期策略(比如 7 天清理),否则数据膨胀速度会吓到你。Gitea 因为仓库都走的git协议,磁盘占用相对可控,但也要留好余量,尤其是团队频繁用 LFS(大文件存储)的话,Git 仓库体积也会突飞猛涨。

6. 按团队类型给出的选择建议

6.1 适合选 GitLab 的团队特征

我总结了一下,如果你符合下面任意几条,选 GitLab 更稳:

  • 团队规模超过 20 人,有正式的技术管理者或 DevOps 角色,需要细粒度的权限控制和审批流。
  • 你们已经或即将正经跑 CI/CD,想让流水线、部署、代码托管在同一个平台闭环。
  • 公司有合规要求(金融、医疗、政企)——需要内网部署、审计日志、SSO/LDAP 集成、数据加密等。
  • 你们会频繁做代码审查和分支策略管理,希望把质量卡口沉淀在系统规则里。
  • 预算充裕,愿意在服务器资源和运维人力上投入(包括 GitLab Runner 的管理)。

6.2 适合选 Gitea / Gogs 的团队特征

反过来,下面这些情况就果断选轻量级方案:

  • 团队 10 人以下,仓库数量个位数到几十个,核心诉求就是代码托管和基本协作。
  • 服务器资源有限,不想为了代码托管专门配一个大机器。
  • 没有专职运维,开发者自己兼任运维,要尽可能降低维护成本。
  • 对 CI/CD 需求比较简单,或者已经在用 Jenkins / 外部 CI,GitLab 内置 CI 的优势发挥不出来。
  • 更在意响应速度和部署简单,不想面对 GitLab 这种“全家桶式”的复杂度。

6.3 做决策前问自己三个问题

第一问:团队有多少人?20 人是分水岭,人越多,权限和规范越重要,轻量方案的“轻”就会变成“不足”。

第二问:未来两年会走到什么规模?如果下个月就要招一波人、走正规军路线,那从第一天就上 GitLab 比以后迁移再学习要省力太多。

第三问:这个平台在你团队里承担什么角色?如果你只想当网盘来用,放代码就是它最大的意义,那轻量级对你就是最优解;如果你希望它变成研发流程的枢纽,让提交、审查、部署环环相扣,那 GitLab 的完整闭环价值就凸显出来了。

7. 从轻量级迁移到 GitLab 的路径

有朋友问过:如果先用 Gitea 跑了一段时间,后期要切到 GitLab,麻烦吗?我的经验是可以顺利迁,但要提前规划。

Git 仓库迁移的核心其实就两条:

  1. 在 GitLab 上建好对应的项目(group/project)。
  2. 在本地把原 remote 地址改成 GitLab 的仓库地址,git remote remove origin然后git remote add origin git@gitlab.example.com:group/project.git,推送所有分支和 tag。如果想保留所有提交历史和分支,用git push --mirror一次搞定。

要注意的是,Gitea 的评论、Issue、PR 历史不会跟着 Git 仓库走。迁移过去的只是代码,上线几年积累的讨论记录需要从 Gitea 导出,或者放弃历史(有些团队觉得无所谓,但做审计的人会很心疼)。如果特别在意这些数据,可以考虑用 API 脚本把 Issue 和 PR 的标题、描述批量同步过去,但附件、评论关联、状态流转的恢复难度很大,很多时候不值得硬来。

还有一个思路是先上 GitLab,然后把 Gitea 当只读归档库保留,再逐步把活跃项目迁移到 GitLab。这样过渡会更平滑,也不怕旧数据丢失。团队项目中历史文档和数据是重要的参考,一次性切换风险较大,分阶段迁移会更稳。

8. 最后再分享两个小技巧

我用了这么长时间发现,无论你选哪个方案,有两个动作都能帮你少踩很多坑:

第一,先把 Nginx 反向代理落好再开防火墙。不管 GitLab 还是 Gitea,最稳定、最省心的访问方式是让它们监听本地 127.0.0.1,然后用 Nginx 做 TLS 终端(HTTPS),80/443 由 Nginx 统一管。这样以后改端口、加域名、接 CDN,都不需要动代码托管服务本身的配置。GitLab 尤其如此,它自己的 Nginx 组件和宿主机 Nginx 共存时容易搞出一堆问题。

第二,让管理员定期手动浏览一次页面的“系统维护”或“后台任务”。GitLab 后台有时候会静默列出一些迁移任务或升级提示,如果没人看,等到下一次发布时很有可能会被奇怪的迁移错误挡在门外。Gitea 相对省心,但也不要等到磁盘空间耗尽才想起来看。

最后再提一嘴,如果你是那种组建十人以下技术团队、想快速把代码托管跑起来的朋友,我真心建议先给 Gitea 一个机会。它太轻了,你部署完会发现:原来代码托管可以这么安静、这么“隐形”,不用整天想着照顾它。而当你某天打开后台,发现团队规模已经悄然涨到了几十人,审批流、流水线、审计记录这些词开始频繁出现在需求里的时候,再抬头看看 GitLab 那面旗帜——那才是它该登场的时候。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 12:17:49

三路超清采集盒H300实战:多机位直播搭建与OBS切换全指南

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

作者头像 李华
网站建设 2026/9/6 12:17:18

应用程序进入中断模式

大白话解释这个报错你的应用进入了中断状态,但当前未执行任何受选定调试引擎支持的代码说白了:VS断点没扎到你写的C#代码上, ZwCAD本身程序崩/卡住了,停在了ZWCAD内部原生代码里,不是你的托管C#代码。所以VS看不到代码…

作者头像 李华
网站建设 2026/9/6 12:16:32

物联网智能控制柜技术参数表详解:从选型到现场部署避坑指南

你是不是也有过这种经历:手上拿到一份“物联网智能控制柜技术参数表”,从项目需求会到采购审批,来来回回折腾了好几天,结果参数表里那些数字和术语要么看不懂,要么看着都差不多,最后选回来的柜子到现场一装…

作者头像 李华
网站建设 2026/9/6 12:16:06

单因素方差分析详解:从组间变异到F检验的完整指南

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

作者头像 李华
网站建设 2026/9/6 12:13:56

保定市涿州市办公环境调理大师

京津冀办公环境调理指南:对话传统文化顾问姜上老师在京津冀地区,尤其是保定涿州这样历史悠久、文化底蕴深厚的城市,越来越多的企业主和职场人士开始关注办公环境的布局与个人发展的关系。大家常有困惑:办公室怎么坐才顺&#xff1…

作者头像 李华
网站建设 2026/9/6 12:13:33

Hy4 preview 770B MoE开源模型部署与WorkBuddy实操指南

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

作者头像 李华