Gitit 是我用了很长一段时间的 wiki 系统,它的设计思路一开始会让人觉得不太习惯:没有数据库,所有页面就是放在 Git 仓库里的纯文本文件。页面默认用 Markdown 写,也支持 reStructuredText、Org、LaTeX 甚至 HTML;每次编辑自动产生 commit,想回滚版本就 checkout 回去。对已经习惯用 Git 处理一切的人来说,这套逻辑基本不用学。这篇文章我打算把 Gitit 从安装、配置到日常维护和避坑经验完整捋一遍。如果你正在为团队选知识库方案,或者想给个人笔记找一个能长期沉淀的存储结构,这篇应该能帮你省不少时间。
1. Gitit 到底解决了什么问题
1.1 传统 Wiki 的维护成本从哪里来
做过知识库选型的人应该都有体会:传统 wiki 平台功能是丰富,但运维负担不轻。数据库要单独建库、定期备份,Web 服务要配运行环境,上传的附件散落在磁盘目录里,权限配置通常得到后台点很久。真要把一套 wiki 长期养起来,这些事一件都躲不掉。我第一次尝试旧式方案时,维护工具的功夫比写页面还多。
Gitit 走的是另一条路。它的所有页面内容就是一个普通 Git 仓库里的文本文件,没有数据库,没有单独的附件存储逻辑。你写一个页面,本质是往仓库里提交一个文件;每一次修改,自动生成 commit。这意味着备份、迁移、审计这套最麻烦的事,全被你已经很熟悉的 Git 工作流接管了。对于一个以内容为核心、不想被运维拖住的小团队来说,这种减法非常关键。
1.2 “版本库即数据库”的设计逻辑
Gitit 的核心思路可以浓缩成一句话:把知识库当成代码仓库来管。页面默认是 .page 文件(内容是 Markdown),也可以用 .rst、.html、.tex 这类扩展名,Gitit 内部通过 pandoc 把它们统一转换成 HTML 输出。你在浏览器里看到的排版效果,其实是一套编译转换的结果。
这种设计的直接好处有三个。第一,内容可移植,哪天不想用 Gitit 了,这些 .page 文件拿出去就是普通文本,不会像某些平台那样要导出一大堆 XML 还得二次处理。第二,历史可追溯,每个页面的编辑历史、修改人、改动 diff 全在 Git log 里,误删误改可以随时找回来。第三,状态易复制,整个系统几乎无状态,测试环境和生产环境之间搬知识库,无非是克隆一次仓库的事。
我实际用下来还有个隐藏好处:因为页面是文本,你可以在服务器上直接 grep 内容做临时排查,也可以用脚本批量改所有页面。这在传统 wiki 里往往要写很绕的 API 调用才能做到。想想看,知识库的各个页面直接暴露为文件系统,很多脑洞都变得可以实现。
1.3 适合什么场景,不适合什么场景
Gitit 最适合的是小团队知识库、个人笔记库、课题组资料整理这类场景。用户量不大,需求以写、查、改、回滚为主,不太需要复杂的审批流和精细的权限矩阵。特别是团队里已经全员习惯用 Git 的话,几乎不需要额外培训,上手的路径很顺。
但如果你的需求是大量用户同时在线编辑、需要字段级权限、要实时协同、要处理海量图片视频附件,Gitit 就不是最优选了。它不是实时协同工具,也没有做附件管理的野心。选错工具比没有工具更痛苦,这个边界要提前想清楚,别等到页面堆了几百张再换方案。
2. 环境准备与安装部署
2.1 需要准备的运行环境
Gitit 是 Haskell 写的,但好消息是,日常使用者不需要懂 Haskell。安装前只需确认系统里有 Git,并且决定好要用的端口没有被占用。如果你选择从源码编译,那需要准备好 GHC 和 Stack/Cabal 工具链;如果嫌编译麻烦,可以直接用发布页的预编译二进制包,或者用系统软件源里现成的包。
我个人在不同机器上两种方式都试过。预编译包最省事,解压就能跑;软件源里的包好处是随系统更新,坏处是版本可能偏老;源码编译能拿到最新版,但 Haskell 工具链的首次构建时间比较长,要有点耐心,头一次编译等上几十分钟、一小时很正常。初次体验的朋友,我建议从二进制包开始,先把功能摸熟,再考虑要不要折腾新版。
2.2 初始化一个最小可运行实例
以最简方式为例,先建一个工作目录,在里面初始化 Git 仓库,然后写一个最基础的配置文件:
mkdir mywiki && cd mywiki git init wiki-repo然后创建 gitit.conf:
repository-type: git repository-path: ./wiki-repo port: 5001 default-extension: markdown启动服务:
gitit -f gitit.conf浏览器打开http://localhost:5001就能看到默认首页。系统里初始管理员账号是 admin,初始密码是 admin,登录后第一步应该去改掉默认密码,这一步很多人会忽略,后面就容易出事。
提示:repository-path 指向的目录必须是已经存在的 Git 仓库。如果目录不存在,Gitit 启动会直接报错,而不是帮你自动初始化,这个和很多人的直觉不一样,第一次用很容易踩。
2.3 容器化运行的额外收益
如果你用的是容器化的基础设施,Gitit 也有现成的镜像方案,一条命令就能起一个实例,数据目录挂载成本地卷。这种方式最适合快速验证场景:几分钟起一个临时 wiki,给项目组做原型展示,不合适就删掉重建,没有任何负担。
容器方案要注意挂载点的持久化,特别是仓库目录和缓存目录都要挂出来。我见过有人只挂仓库目录,结果升级容器后缓存丢失,虽然不影响内容,但首次访问速度会明显变慢,等于把冷启动问题重新引了回来。宁可把整份工作目录都挂载出来,也别做半吊子持久化。
3. 核心配置与页面语法解析
3.1 配置项逐条拆解
Gitit 的配置集中在 gitit.conf 里,格式是缩进式的键值对。下面列几个我实际调过、也觉得最值得了解的配置项:
| 配置项 | 作用 | 我的建议 |
|---|---|---|
| repository-type | 仓库类型,git 或 darcs | 默认 git,不用改 |
| repository-path | 仓库路径 | 用绝对路径,避免启动目录不同导致混乱 |
| port | 监听端口 | 对外服务建议放到 80/443 后面做反向代理 |
| default-extension | 新建页面默认使用的标记语言 | markdown 最通用 |
| cache-directory | 缓存放目录 | 放内存盘可提速,但重启丢缓存没关系 |
| limit-upload-bytes | 上传大小上限 | 按团队实际需求调 |
| math | 数学公式渲染方式 | 写技术文档建议开启 |
| table-of-contents | 是否自动生成目录 | 长页面很有用 |
不要一次把所有配置都加上。Gitit 的默认配置已经能跑得很稳,配置项加得越多,排查问题时的变量越多。我通常先跑默认,再按需一项项加,每加一项就观察一阵,确认没有副作用再加下一项。
3.2 页面语法与格式转换链
Gitit 页面用双括号[[页面名]]做 wiki 链接,这是它最常用的语法。除此之外,正文用的就是标准 Markdown,包括表格、脚注、任务列表等。如果你写的是 .tex 页面,还能直接享受 LaTeX 的排版能力;默认情况下,Markdown 页面里也能用$...$写行内数学公式,配合 math 配置项渲染成漂亮的公式效果。
格式转换链是这个项目的精华:所有页面先经过 pandoc 解析,再渲染成 HTML。这意味着你几乎可以把 pandoc 支持的输入格式都当作 wiki 页面格式来用。我试过把一个写了大半年的 Org 笔记迁移进去,页头稍微调整就能直接用,迁移成本比我预想低很多。正因为有 pandoc 在底层兜底,Gitit 的页面格式不会像某些 wiki 那样自创一套语法,学起来几乎没有额外负担。
3.3 模板与插件机制
如果不想让页面长得像默认主题,Gitit 的模板目录可以改。templates 目录下有 default.html、page.html 等模板文件,用的是简单的占位符语法,能把页面内容、侧边栏、页脚插到任意位置。我当时把顶栏导航、站点标题等全部换成了团队风格,大概花了半天时间,效果立竿见影。
插件则是给掌握 Haskell 技能的人准备的高级扩展点。插件可以挂接页面渲染、附加元数据、定制命令等环节。多数人用不到插件,但如果你懂一些 Haskell,会发现这套插件机制做得规整、边界清晰,很适合深度定制。不会 Haskell 也完全不影响日常使用,扩展能力是加分项,不是必需品。
4. 实操:搭建一个团队知识库的全过程
4.1 规划目录结构与命名规范
我搭建团队知识库时,第一步不是配服务,而是定目录和命名规范。Gitit 的页面名会直接影响 URL 和链接写法,所以最好统一成小写字母加连字符,比如 team-onboarding、daily-standup-notes。目录方面,我习惯按领域拆:engineering、product、operations、research 这样分,每个目录下放对应分类的页面。
命名规范一定要在团队 wiki 的第一页就用文档固定下来,否则一个月后页面名就开始混乱,链接写得到处都是。不要用带空格的页面名,链接写起来麻烦,URL 也不好看。中文页面名虽然能工作,但混合编码的链接在不同浏览器里表现不一致,我自己吃过亏,后来统一不用中文做页面名。
4.2 协作流程与版本管理
团队协作时,我会给每个成员建一个独立账号,密码各自保管,然后通过 Git 的提交记录就能知道谁改了哪个页面。这个审计能力是 Gitit 天然自带的,不需要额外配置插件。页面编辑保存后,后台自动 commit,提交信息会带上编辑者信息。
如果团队里有成员希望本地用编辑器写文档而不是在浏览器里敲,可以考虑这样的玩法:把 wiki 仓库共享为远程仓库,成员本地克隆后写页面再 push,服务端拉取后页面即更新。这种方式需要对 Git 冲突有一点准备,但它让 wiki 内容彻底变成了“普通人也能维护的代码仓库”。我在跨机器同步笔记时就采用这个思路,体验很顺,唯一的代价是要记住“拉取再推送”这个节奏。
4.3 典型页面示例:从会议纪要到技术文档
会议纪要是 wiki 用得最多的场景之一。我在工程团队里常用这样一种模板页面:
# 项目周会纪要 日期:2025-01-08 记录:A同学 ## 本次主题 - 上周遗留事项同步 - 新功能模块评审 ## 待办 - [ ] 接口文档补充 - [ ] 性能基线测试 ## 备注 相关设计见 [[search-architecture]]这种页面的价值在于:它既是一份可检索的记录,又通过[[search-architecture]]这样的链接把相关决策串起来。技术文档同理,把背景、方案对比、结论写在同一个页面里,再用链接指向相关模块,知识库就会慢慢长出结构,而不是一个纯堆文件的网盘。坚持几个月后,页面之间的网状关联会越来越密,检索价值也随之上升。
4.4 备份与恢复策略
备份 Gitit 几乎是最省心的:把 gitit 服务停掉,对整个仓库目录打一个压缩包,或者用 git bundle 生成一份完整历史快照。恢复时解压放到新机器上,配置指向这个仓库,启动服务,完事。整个过程不需要导出数据库,不需要考虑附件目录和数据库的一致性,这些在其他 wiki 上是最容易出错的部分,在这里直接不存在。
我在实际操作中会额外保留一份离线冷备份,每周自动把仓库打包上传到异地的存储位置。日志和缓存可以不备份,丢了会自动重建,只有仓库目录是不可再生资源,这个优先级要分清。备份频率取决于团队更新量,更新频繁就每周,个人笔记可以放宽到每月,但一定要有,否则版本历史带来的安全感就是空中楼阁。
5. 常见问题与排查技巧实录
5.1 常见问题速查表
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 启动报仓库路径错误 | repository-path 指向空目录或不存在 | 先 git init,再启动 |
| 忘记管理员密码 | 初始密码未及时修改 | 停服务,修改仓库内的用户配置后重启 |
| 页面显示原始内容 | pandoc 转换异常或页面扩展名不对 | 确认页面扩展名是 .page |
| 上传文件被拒绝 | 超过 limit-upload-bytes 限制 | 调整该配置项后重启 |
| 多人同时编辑丢改动 | 页面保存冲突 | 查看 Git 历史,取回被覆盖的版本 |
| 首次打开页面很慢 | 页面尚未缓存,正在走转换流程 | 预热常用页面后即恢复 |
这张表是我自己踩坑过程的浓缩版。比起记住每个答案,更重要的是建立排查思路:Gitit 的绝大多数问题都出在仓库、缓存、配置这三块,按这个顺序找,通常很快能定位。
5.2 我踩过的几个坑
第一个坑是反向代理配置。把 Gitit 放在反向代理后面时,如果代理没有正确传递 Host 头,登录状态会异常,页面链接也可能变成内网地址。处理方式是在代理配置里显式设置相关头信息,这个排查看似不起眼,但当时折腾了我一整个下午。
第二个坑是 PDF 导出。Gitit 支持通过 pandoc 导出 PDF,但要求系统里装了相应 LaTeX 引擎。很多服务器是精简环境,缺字体缺编译套件,导出时要么乱码要么直接失败。解决方案是提前在目标系统里装好一个合适的 TeX 发行版,再配置 pandoc 的 pdf 引擎参数,不要在出问题后才临时补东补西。
第三个坑是缓存目录权限。如果运行 gitit 的用户对缓存目录没有写权限,它会表现为页面偶发加载失败或者后台一直报错,非常迷惑,表面上看起来和缓存毫无关系。处理方式很简单,把缓存目录所有权交给运行服务的管理用户,或者直接用系统临时目录,别自作聪明放到奇怪的位置。
5.3 性能表现与调优方向
Gitit 本身的性能特点是:静态页面请求很快,首次访问未缓存的页面时,pandoc 转换会占一点时间。在团队规模不大的前提下,这个瓶颈几乎感觉不到。如果确实要优化,方向有两个:一是把缓存目录放到更快的磁盘上,二是用脚本预热核心页面,让高频页面提前生成缓存,避免用户第一脚踩到冷启动。
另外,全文搜索在页面数量很大时会明显变慢,这时候需要考虑拆分:把资料按主题拆成多个独立仓库,每个仓库一个 Gitit 实例,效果往往比调优一个巨型实例更明显。毕竟搜索慢的本质是数据太集中,拆分才是更彻底的办法。我见过上百个页面的实例跑得还不错,但超过这个量级之后,拆分是更务实的路径。
6. 个人使用心得与可扩展方向
6.1 用下来最值得的三个方面
第一是版本历史带来的心理安全感。写错、误删、被覆盖,这些事情在普通 wiki 里是很严重的故障,在 Gitit 里只是日常操作。有一次我整理旧文档时误删了一个页面,一周后才发现,登录服务器用 git log 找回来,前后不到五分钟。这个体验足以抵消它很多小缺点。
第二是纯文本的可维护性。所有内容都是普通文件,可以用脚本批量处理,可以生成静态快照发布到只读站点,可以随时做格式转换,完全没有被平台绑架的感觉。对我这种喜欢折腾的人来说,这意味着知识库可以接入任意工具链,而不是被一个封闭平台锁死。
第三是资源占用极低。跑一个小团队的 wiki,内存占用在百兆级别,CPU 平时基本空闲,丢在一台廉价服务器上毫无压力。对于习惯把成本压到极致的团队,这个优势很实在,也意味着它可以长期稳定地运行而不需要三天两头扩容。
6.2 后续可以继续折腾的方向
如果玩熟了基础功能,有几个方向值得试试。用 Git 钩子在每次提交后自动导出页面为 HTML 或 PDF,形成静态发布流程;用定时任务把系统里散落的 Markdown 笔记自动提交进 wiki 仓库,把知识库变成日常输入管道的一部分;甚至可以尝试把多个 Gitit 实例的文件系统共享到同一份仓库目录,做成简单的主备架构。
我自己目前在做的扩展是把团队 wiki 的仓库和 CI 流程联动:每当 wiki 仓库收到推送,CI 自动把变更内容同步到内部文档站的只读入口。这样一来,wiki 既是编辑后台,又是文档发布的源头,一个仓库同时解决了两件事。最后再分享一个小技巧:如果想让 wiki 页面在外部只读展示,可以用脚本把渲染好的 HTML 批量导出成静态目录,丢给任意静态托管即可,这样知识库既能内部编辑又能对外发布,两条路都不耽误。