十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

开源Markdown在线笔记:一键保存到Git仓库,让数据自主可控

开源Markdown在线笔记:一键保存到Git仓库,让数据自主可控 1. 项目缘起为什么我需要一个“Git仓库即云盘”的笔记工具先说个我自己的真实场景。过去几年我一直在折腾各种在线笔记从早期的印象笔记、为知到后来的Notion、语雀再到各种开源自部署方案。工具换了一轮又一轮最核心的痛点始终没解决数据不自由。你用某个在线笔记数据就在人家的服务器上。今天它出了个新条款明天服务调整了某个功能或者哪天你网不好、公司网络抽风笔记就打不开了。更别提有些平台导出格式各种私有化想迁走比搬家还累。我自己就经历过一次笔记平台功能调整导致排版全乱的糟心事从那以后我对“笔记数据必须在本地有一份可控副本”这件事有了执念。后来我接触到一个思路其实很多人已经在用了用Git仓库当笔记的存储后端。Markdown本身就是纯文本天然适合用Git做版本管理。每一次编辑都是一次commit历史版本一目了然回滚也方便配合GitHub、GitLab、Gitee这些平台跨设备同步问题也解决了——不只解决了还顺手解决了“数据归谁所有”这个根本问题。于是就有了这个开源项目一个Markdown在线笔记编辑工具核心能力就一句——让你在浏览器里写Markdown笔记一键保存到你自己的任何主流Git仓库。项目本身我开源出来了本地跑起来就能用数据完全由你掌控。这个项目适合谁我觉得有几类人特别值得试试本来就在用GitHub/Gitee/GitLab管理代码和文档的开发者笔记顺手就进去统一管理。对笔记数据主权有要求、不想被某个在线服务锁定的用户。想用Markdown写作但觉得直接传文件到Git仓库太麻烦、想要一个舒服的编辑界面的人。有自部署习惯喜欢把所有服务都跑在自己NAS、服务器或树莓派上的人。这篇文章我会把整个项目的设计思路、技术选型、部署方式、实际使用体验以及踩过的坑全部摊开来写清楚。无论你是想直接用这个工具还是想参考这个思路自建一套都希望能帮你少走弯路。2. 整体设计思路为什么“在线编辑Git同步”是笔记场景的最优选2.1 核心痛点拆解笔记工具到底该解决什么问题做这个项目之前我认真做了一轮需求梳理。一个笔记工具在我看来至少要满足这么几个诉求第一是写作体验。编辑器必须好用所见即所得渲染流畅代码块、表格、数学公式这类技术写作常用的能力一个不能少。我不是针对谁但技术类笔记经常要贴代码、画流程图、做表格这个需求在线笔记里属于刚需。第二是存储机制。这就是前面说的数据自由度问题。笔记内容必须能随时导出、随时备份、随时迁移。最好存储格式就是一个开放的纯文本标准这样即使工具本身出了问题笔记数据也永远能用其他工具打开。第三是可追溯性。这个被大多数人忽略了但实际用过之后会发现它极其重要。写笔记不是写代码但笔记同样有“改错了想回退”的需求同样有“我上周写的比现在这版好”的后悔药需求。版本管理不是程序员的专利笔记也需要历史版本能力。第四是轻量。不能为记个笔记跑一堆庞杂的服务不能系统占用极高不能每次打开要等半天。工具应该是打开浏览器就能用的删掉也不心疼。这四个需求摆在一起“Markdown编辑器 Git仓库远端存储”这个组合几乎是标准答案拆开看每一条都能对上Markdown是开放格式纯文本存储任何编辑器都能打开。Git天然自带完整版本历史每次保存就是一次版本快照回滚也就一条命令的事。Git平台本身提供了跨设备同步能力GitHub、GitLab、Gitee都有成熟的云端托管服务。所以项目最开始定调就很清晰做一个把“Markdown的写作体验”和“Git的版本管理能力”真正融合的工具而不是简单地在网页上套一个编辑器再调Git命令行。2.2 技术选型编辑器、Git操作、后端框架的取舍技术选型阶段我重点在这几个方面做了比较。Markdown编辑器是核心中的核心市面上主流开源方案有CodeMirror、Monaco Editor就是VS Code用的那个编辑器核心、以及一些开箱即用的Markdown编辑器。我最终选择的是基于CodeMirror 6的一套自封装方案主要原因是CodeMirror 6的模块化设计非常有吸引力按需引入核心包只有一百多KB相比Monaco动辄几MB的体量轻得多。而且CodeMirror的Markdown支持扩展性极强后续要加自定义语法、实时预览、代码高亮都方便适合做深度定制。Git操作这一层曾考虑过两个方向一是后端直接调用系统安装的git命令行二是用isomorphic-git这样的纯JavaScript实现。这两种我都做过多轮验证最终选了后端调git命令行的方式。原因有几个系统的git客户端成熟稳定处理各种复杂的远端交互、凭证管理、合并算法都不容易出问题而isomorphic-git在浏览器端操作Git虽然很酷但对于大仓库支持不够好性能有明显瓶颈涉及HTTP协议兼容性时也偶尔会踩坑。对工貝类应用来说稳定压倒一切。后端框架选型相对简单因为项目本身逻辑并不复杂核心就是接收前端编辑器的内容通过git命令完成提交、推送、拉取等操作。我用的是Node.js生态的Express框架配合一些轻量的工具库整个服务端代码总量很少维护起来也舒服。这里没有引入重量级的数据库笔记内容本身就在Git仓库里应用的内部状态用简单的文件存储就足够了能少一个依赖就少一个。2.3 竞品分析与差异化和市面上已有方案比强在哪其实“Markdown笔记 Git同步”这个方向并不是全新概念市面上已经有一些类似的开源项目。这里我梳理了一下同类方案的差异化让整个设计的定位更清醒方案编辑器体验仓库支持自部署难度版本可视化项目侧重点Logseq双链笔记体验好但模式偏专属支持Git自动同步中等一般大纲式知识管理Obsidian官方同步体验好但同步功能付费官方同步非Git原生低无本地知识库Joplin中规中矩支持Git同步但配置稍繁琐中等弱全平台笔记本项目方案浏览器在线即用零客户端依赖GitHub/Gitee/GitLab原生直连低有提交记录时间线轻量在线Markdown Git仓库对比下来这个项目的差异化核心能总结为三点。一是部署足够轻。其他很多方案是需要客户端安装的或者自部署时需要搭配数据库。这个项目单一服务进程一条命令启动前端页面做完就全静态托管整体资源占用很低跑在树莓派上都毫无压力。二是Git仓库是第一公民。不是“把Git当一个同步通道”而是整个操作的逻辑都围绕Git展开。你可以在工具里直接切换分支、查看历史提交、一键回滚这些对熟悉Git的人来说是极大的便利。三是不锁定任何平台。Git 仓库可以放在 GitHub、Gitee、GitLab也可以是你自己搭建的Git服务器甚至局域网里的一个裸仓库。工具本身不绑定任何特定云服务商这个自由度在同类工具里不多见。3. 核心功能拆解与实操要点编辑器能力、仓库配置、分支管理3.1 在线编辑器的完整功能面写作体验不能将就在线编辑器是整个项目体验的“脸面”这块我花了很大功夫。先说一下它支持哪些能力基础Markdown语法标题、加粗、斜体、删除线、引用、有序列表、无序列表、任务列表、分割线这些常规语法在编辑区输入后右侧预览区实时渲染光标位置和预览区域做了同步滚动方便边写边看。技术写作增强这是和普通笔记拉开差距的地方。代码块支持语言识别和语法高亮覆盖的主流语言包括JavaScript、Python、Go、Java、C/C、Rust等数学公式用KaTeX渲染速度和渲染质量都比传统MathJax好支持Mermaid流程图、时序图、甘特图的渲染表格语法实时预览支持对齐。写技术笔记和文档的时候这些能力几乎每日必用。图片与附件处理本地图片直接拖拽进编辑区会自动处理成Base64格式暂存保存时会上传到Git仓库的指定资源目录并把图片引用路径同步更新。这块细节处理了很多轮后面常见问题里我会专门讲一个关于图片路径的坑。其他体验细节自动保存的防抖策略我设置的是停止输入3秒后自动触发一次保存检查、编辑历史本地快照防止浏览器崩溃丢稿、全屏专注模式、字数统计、目录大纲自动生成。这些细节不花哨但对每天写的人来讲很实用。3.2 打通Git仓库认证配置与多平台支持细节这一节是整个工具最关键的实操部分我把配置流程和一些细节建议都写清楚。第一获取仓库访问凭证。主流Git平台都已经逐步停用账号密码直接访问仓库现在统一推荐使用Personal Access Token简称PAT个人访问令牌。不同平台的生成路径不一样GitHub是在Settings → Developer settings → Personal access tokensGitee是在设置 → 私人令牌GitLab是在偏好设置 → 访问令牌。创建令牌时要注意给它足够的权限范围一般需要勾选repo相关的读写权限如果用的是私有仓库还需要额外确认权限覆盖范围。提示生成的令牌本身相当于一把钥匙务必只保存在本地配置中不要提交到任何代码仓库或公开场合。Git平台通常只会完整显示一次令牌后续无法再次查看。第二配置仓库信息。工具首次使用的引导页面需要填写远端仓库地址、用户名、令牌、分支等关键信息。这里有个容易踩坑的地方仓库地址建议用HTTPS格式不要用SSH格式。因为工具后端通过git命令行操作远端SSH方式会在服务端牵扯到密钥管理复杂度高且容器化部署时密钥挂载也比较麻烦。HTTPS加令牌的方式干净利落所有平台通用的。配置项的填写格式大致如下仓库地址: https://github.com/yourname/yournotes.git 用户名: yourname 访问令牌: ghp_xxxxxxxxxxxxxxxxxxxx 默认分支: main第三多仓库切换。工具支持维护多套“配置档案”也就是你可以同时配置一个公司的GitLab仓库用来写工作笔记、一个自己的Gitee仓库用来写个人博客、一个GitHub私有仓库用来记技术收藏。切换仓库时工具会先自动检查当前仓库是否有未提交的改动确认后才切换到另一个仓库的工作区避免相互污染。3.3 分支管理、历史版本与一键回滚的交互设计Git的版本管理能力要能真正被不熟悉Git的普通用户用上交互设计就非常关键。我专门做了一套面向笔记场景的简化的分支和版本操作界面。在工具里用户能做的事情包括查看历史提交界面左侧有一个历史记录面板列出当前分支的所有提交记录包括提交信息、提交作者、时间、涉及的修改文件列表。点击任意一条提交可以查看该提交相对上一次提交的完整diff也就是具体改了哪些文字、哪些行一目了然。一键回滚如果觉得某个历史版本比现在的好直接选中那条提交记录点“回滚到此版本”工具内部会自动基于当前仓库状态创建一个新的提交来恢复那些历史内容而不是直接强推覆盖历史记录。这么做能保留完整的历史时间线即使回滚完后悔了也还能再回滚回来。分支创建和切换默认在main分支上写笔记但如果你有一些实验性的写作计划、或者想给某个项目单独建一个笔记空间也可以点击“新建分支”起个分支名后续的内容就都提交到这个分支上。等实验稳定了可以再合并回主分支整个过程在界面上点按钮就行底层的merge操作自动完成不需要手动处理冲突。这里我强烈建议日常笔记都放在一个默认分支上不要频繁开分支。分支是给人多协作或开发场景设计的个人笔记用多了只会搞乱自己。工具里是有分支能力但你完全可以只在主分支上持续commit照样能享受完整的历史版本管理。4. 部署与实操本地运行、Docker一键部署、托管服务器方案4.1 本地快速部署两分钟跑起来先说本地运行这是让项目跑起来最快的路径。前提是你机器上已经装了Node.js建议v18以上版本和Git。# 克隆项目 git clone https://github.com/yourname/markdown-notes-git.git cd markdown-notes-git # 安装依赖 npm install # 构建前端 npm run build # 启动服务 npm start启动成功后浏览器访问http://localhost:3000就能看到界面。首次打开会引导你配置Git仓库信息按照上一节的说明填好就能开始写第一篇笔记了。补充一下如果你打算长时间在线使用还是建议执行一次npm run build生成生产环境的前端静态资源开发模式的服务性能要差不少。另外首次启动前确保本机的git命令在PATH环境变量里可以正常访问可以通过git --version验证一下。4.2 Docker部署一条命令完成自托管考虑到不少用户希望把这个工具跑在NAS或云服务器上我提供了Docker镜像部署更简单不污染宿主环境docker run -d \ --name markdown-notes \ -p 3000:3000 \ -v /path/to/notes-data:/app/data \ -e GIT_USER_NAME你的名字 \ -e GIT_USER_EMAIL你的邮箱 \ --restart unless-stopped \ yourname/markdown-notes:latest这个命令里几个参数说明一下-p 3000:3000宿主机端口映射到容器内服务端口如果是服务器部署记得在安全组放行3000端口。-v /path/to/notes-data:/app/data数据目录挂载。工具的配置文件、仓库本地副本都会在这里升级容器时数据不会丢。-e GIT_USER_NAME和-e GIT_USER_EMAIL提交记录的署名信息建议设置否则提交到Git仓库时作者信息会显示为默认值在远端提交记录里不利于辨认。对于有docker-compose使用习惯的用户配置文件写起来也不复杂核心就一个服务不存在依赖编排的问题。4.3 服务器部署进阶域名、HTTPS、反向代理配置如果你打算把服务正经跑在一台公网服务器上直接暴露3000端口并不推荐。一是裸奔的HTTP协议不安全编辑器内容在传输过程是明文尤其是涉及令牌通过HTTPS之外的方式提交风险太高二是端口直接暴露不够规范。我建议加一层Nginx反向代理把公网80/443流量的转发到本机3000端口同时终结HTTPS。Nginx反向代理配置的核心片段如下server { listen 443 ssl; server_name notes.yourdomain.com; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/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; } }这里有几个反向代理场景下的关键点需要特别提醒如果服务端有处理WebSocket连接编辑器内的实时协同或通知功能会用到需要在Nginx里显式配置Upgrade和Connection头否则连接会被代理中断。前端资源加载路径默认是相对路径但如果部署在子路径比如https://域名/notes/需要设置一个环境变量来指定base path否则静态资源会404。反向代理的高层超时时间建议设置合理值Git推送大文件时单个请求耗时较长默认超时时间可能导致请求被Nginx提前断开推送失败。注意如果编辑器本身没有实时同步需求部署可以省略WebSocket反代配置但文件资源和普通API请求的代理头必须设置正确否则会出现编辑加载失败或页面样式错乱的现象。5. 完整实操演示从配置仓库到完成第一篇笔记5.1 三分钟初始化以Gitee私有仓库为例我用Gitee做一个完整的演示流程GitHub和GitLab逻辑完全一样照着做就行。第一步在Gitee上创建一个空仓库。这里的关键建议是建仓库时不要勾选“初始化仓库”选项也就是不要自动生成README、.gitignore让仓库保持完全空白的状态。如果仓库创建时就有了README文件那远端和本地仓库在初始状态下就已经分叉了推送时需要处理一次冲突。虽然也能解决但没必要不如创建空仓库省事。仓库可见性建议选私有笔记内容毕竟属于个人数据没必要完全公开。第二步在Gitee个人设置页面找到“私人令牌”点击生成新令牌。权限范围建议直接勾选projects相关的读写权限再把令牌复制保存到本地临时文件。这个令牌后面配置到工具里就不再重复使用了。第三步打开工具页面填写仓库配置信息仓库地址: https://gitee.com/yourname/notes.git 用户名: yourname 访问令牌: 粘贴刚才的令牌 默认分支: masterGitee默认分支名是master保存后工具会自动初始化本地工作区、拉取远端状态。第一次配置完成后本地会检测到这是个空仓库工具会提示“未检测到远程默认分支将在首次保存时自动创建”。第四步进入编辑器新建一篇笔记标题输入“我的第一篇笔记”正文可以随便写点内容点击保存。保存完成后再回到Gitee网页刷新仓库页面就能看到我的第一篇笔记.md文件已经出现在仓库里了。这就完成了第一次完整的“本地编辑 → Git提交 → 远端推送”流程。5.2 日常写笔记的工作流三个操作习惯强烈建议养成工具用起来后我分享几个日常使用效率明显提升的操作习惯。习惯一文件组织用目录不要一锅乱炖。在工具里新建笔记时可以带路径比如说技术文档/Vue3/响应式原理.md、项目会议/20250110需求评审.md前端会按目录结构展示笔记列表。这样仓库里文件也和本地一样有清晰的层级远端管理一目了然。习惯二提交信息写得一目了然。每次保存时工具会默认生成一条提交信息格式是update: 文件名。但你有权改成更具体的描述比如“补充了内存泄漏的案例分析”。提交信息是Git历史的重要索引一个月后靠的就是它来找某次改动。习惯三出门在外遇到值得收藏的内容顺手就贴到临时收集箱。我在工具里设了一个专门的“收集箱”目录每天把碎片信息、临时链接、突然想到的点子都丢进去不分类不整理。到周末花二十分钟把收集箱里的内容按主题归档写笔记的效率会高很多。5.3 多设备同步场景公司电脑、家里电脑、手机怎样保持一致跨设备同步是这个项目相对传统在线笔记的强项因为底层就是Git仓库天然支持多设备拉取推送。但这里有一个很关键的体验问题不同设备不可能同时在线所以“多设备同步”本质上是一个异步过程——设备A推送 → 设备B拉取。工具把这个过程做了自动化处理每次保存时会先自动拉取远端最新内容如果检测到没有冲突就直接在本地最新版基础上追加提交并推送如果检测到远端有别人改过或者设备B也改过同一份文件工具会提示冲突并提供手动处理选项。我实际用了这几个月多设备同步的场景总结下来场景操作效果公司在电脑写回家继续打开工具自动拉取最新提交直接看到最新内容继续写手机临时记录通过短信/邮箱转文字电脑端汇集后在编辑器统一归档信息不丢失回电脑系统化家里和公司同时改了同一篇笔记自动检测冲突编辑器打开带冲突标记文本手动保留所需内容重新提交就个人笔记场景来说多设备同时改同一篇文件的概率很小上面第三种情况极少发生但工具已经做好了兜底不会出现内容悄然覆盖的情况。6. 常见问题与避坑实录6.1 认证失败与权限问题排查问题现象保存笔记时提示认证失败或一直让你输入账号密码、或返回403 Forbidden / 401 Unauthorized。原因与处理这个问题的原因基本跑不出下面几种令牌填错或者复制的时候多出了一个空格。建议在配置页重新复制一次令牌不要在前后端来回粘贴。令牌权限不足。检查创建令牌时是否勾选了仓库读写权限repo相关。有些平台默认生成只读令牌自然无法推送。用户名不是昵称是登录账号。Gitee和GitHub的用户名是登录时的账号名不是昵称。远端仓库地址写错比如少了.git后缀或协议头。6.2 保存失败提示“远端有更新”问题现象保存时报“non-fast-forward”或“远端有更新请先拉取”。原因与处理本地和远端的提交历史出现了分叉也就是说远端有本地看不到的新提交。正常情况下工具会自动拉取并合并但特殊情况比如远端有人做了历史的rebase操作或者手动强推过下自动合并会失败。这时候需要手动处理第一步在设置页面点击“同步远端状态”第二步如果仍失败可在服务器上进入工具的数据目录手动执行git命令诊断解决cd /path/to/notes-data/workspace git status git pull origin main --no-rebase如果确认远端某些历史没用也可以做强制同步。但这要非常谨慎强制推送会覆盖远端历史如果远端有别人也在用多设备共用会导致其他人的仓库状态不一致所以要确认无误后再执行git push origin main --force6.3 图片在笔记里正常显示但Git仓库里打不开这个坑我踩了挺久直接说结论。图片上传策略需要配合Git平台的处理方式在克隆到本地后可能渲染不了网络图片。问题的根源在于Git仓库里的相对路径图片在本地Markdown预览器中能否正确渲染取决于编辑器和仓库根目录的相对位置。比如一篇笔记路径是技术文档/Vue3/响应式原理.md里面通过![](../images/xxx.png)引用了一张图片因为在md文件目录的images子目录里。但当工具向远端推送时实际推送的整个仓库图片路径是相对仓库根目录的。如果Git平台网页端预览或工具再次打开时编辑器里解析路径的基准和本地不同这张图就可能加载失败或显示成空。解决方式项目的配置里有一个“统一资源目录”选项建议所有笔记的图片统一存放到一个固定的assets/目录中即仓库根目录下的一个固定的目录。这样图片引用路径一致为![](/assets/xxx.png)不管从哪个位置打开笔记都能正确加载。其他笔记工具中统一目录也是处理图片的最稳妥方案可以把这个当成一个默认规范来遵守。6.4 仓库体积膨胀与性能问题用久了会发现Git仓库越来越大主要是因为笔记里的图片、附件甚至一些误传的大文件都被提交进了仓库。Git 的设计目标本来就不是当网盘用大文件会让仓库体积急剧膨胀每次拉取推送都变慢平台端容量限制也容易触发。目前项目的处理方式是仓库体积超过阈值时提示用户对历史提交进行整理或者对超大不用的历史AST等文件做清理。但说实话这需要用户自己介入处理工具只能尽量提醒。结合我的实际经验建议在日常使用中注意几点笔记正文内容以文字为主图片尽量压缩后再上传手机拍的截图动不动几十MB直接拖进编辑器会瞬间把仓库撑大。遇到视频、音频这类大文件干脆不入库把文件传到对象存储用链接的方式插入笔记。定期用工具内置的“仓库体检”功能查看体积变化趋势把不必要的缓存清理掉。提示Git 是文本管理的利器但不是大文件存储工具。如果实在要存大文件应该考虑Git LFS方案但那是另一个话题了普通笔记场景尽量规避大文件入仓库就好。6.5 浏览器缓存导致的显示异常问题现象编辑器页面样式偶尔会出现错乱或者保存后提示成功但内容没有更新。原因与处理浏览器端缓存了旧版本的静态资源。工具升级后如果nginx或浏览器缓存策略设置得比较激进新版本的JavaScript和CSS文件可能加载不到。处理方式硬刷新CtrlShiftR清除缓存重新加载同时更推荐在Nginx配置里对静态资源启用带hash的文件名规则这样文件内容变化后文件名跟着变化浏览器自然会请求新文件location /assets/ { expires 7d; add_header Cache-Control public, no-transform; }但注意项目已经默认把带hash的静态资源文件名通过构建工具自动生成所以升级后通常不会踩缓存问题如果你是自己二次修改后手拆静态文件才需要额外留意。7. 后续扩展方向与我的实战心得这个项目还在持续迭代中目前我重点考虑的几个方向也顺带分享一下我平时实际用下来的扩展思考。第一个方向是模板系统。写技术方案、写周报、写会议纪要格式相对固定如果能预制一批Markdown模板新建笔记时直接套用能省不少重复敲击的时间。目前项目里有一个简易模板功能后续想扩充成模板市场让社群共享各自沉淀的模板。第二个方向是全文检索。笔记越写越多之后靠文件列表找内容效率很低。Git本身不提供内容检索所以计划在工具层引入一套轻量索引利用内存和磁盘建立Markdown文本的切分词索引实现毫秒级的全文搜索。第三个方向是自托管生态整合。目前支持的主流Git平台已经覆盖绝大多数场景但我也注意到有一些用户用Gitea、GitCode等构建了私有代码托管平台。后续计划完善对这些小众Git服务的兼容性让这套笔记工具能更无缝地嵌入用户已有的自托管体系。最后想聊一点个人体会。做这个项目给我最大的感触是很多“工具不好用”的抱怨本质上是因为工具的设计者和使用者的核心诉求不一致。作为开发者我一直坚持一个原则一个笔记工具好不好不看它的功能列表有多长而是看用户是否感觉自己的数据是安全的、写作过程是否顺心、历史是否可回溯。这三个体验做到位了哪怕功能少一点用起来也会觉得踏实好用。我日常完全是这个工具的深度用户从写这篇文章的初稿到整理日常的技术文档再到记录项目开发的迭代日志全部都在工具里完成。每次打开编辑器看到同步状态显示“已保存到远端仓库”心里就很踏实——无论这个工具以后走向如何、服务有没有关停这些笔记数据都安安稳稳地躺在自己的Git仓库里谁也拿不走随时可迁移这就是我认为一个“好用”的笔记工具最该有的底线。
返回列表