@076lik/git-panel
v3.2.1
Published
轻量级局域网 Git 仓库与 CI/CD 管理平台
Maintainers
Readme
Git Panel
本地 Git 仓库与 CI 流水线管理平台,提供类 GitHub 的 Web 界面。
它不是 Demo,而是已在生产环境长期运行的完整平台:本机(龙芯 loongarch64 / AOSC OS)上托管着 9 个真实仓库,年复一年地承担推送、构建、部署与外部同步。文中列出的每一项能力都在真实仓库上验证过,包括那些"只在出问题时才用得到"的部分(快照回滚、孤儿构建校正、失效地址清理)。
零认证、零数据库、纯文件系统存储:插上硬盘、跑一条命令就能用。

更多界面见下方界面预览。
功能特性
仓库与协议
- 三重协议并行:Git Smart HTTP(可推可拉)、SSH、
git://daemon,局域网内免认证开放 - 任意存储路径:仓库根可放在外部硬盘/USB,Web 界面一键修改;路径解析在后端、部署脚本、CI 三处统一
- Git LFS 服务端:完整的 Batch API(上传/下载协商),支持一键启用与关闭(关闭时保留对象,不破坏历史提交)
- 分支与标签管理:创建、删除、切换;分支切换状态不会被刷新重置
- 文件浏览:目录树、README 渲染、原始字节下载、归档打包下载
- 多格式预览:JSON 树、CSV 表格、Diff/Patch 着色、Log 级别高亮、PDF/图片/视频/音频、Markdown
- 文件树实时搜索、全库代码搜索
- 分支对比:任选两个分支/标签,查看文件级差异(状态、增删统计、按需展开单文件 patch)
- 提交 diff 查看器:点击提交查看该次改动的文件列表与逐文件差异
- 语言统计:基于
cloc,自动排除文档/配置/脚本
存储与快照
- 三级快照降级链:btrfs 原生只读子卷快照(零额外空间、秒级)→ reflink 复制(XFS 等)→ 普通复制(ext4 等)
- 不支持的磁盘自动退回普通复制,并在界面上明确提示会占用额外空间,绝不静默失败
- 子卷转换:把已有仓库原地转为 btrfs 子卷以启用原生快照,失败自动回滚(
fsck校验、旧数据不丢) - 快照恢复:btrfs 用原子换名,保留原快照;支持快照列表、删除与保留策略
CI/CD
- 推送自动触发构建:
post-receive钩子从 stdin 解析真实分支并自动校正悬空 HEAD - CI 配置自动识别:GitHub Actions / GitLab CI 兼容,另有 Python·UV / C·C++ / Go / Rust / Java / TypeScript / Lua 多语言模板
- CD 持续部署:构建成功后执行部署步骤,也支持手动触发
- 构建看板与统计:历史趋势、成功/失败占比、日历热力图
- 构建日志:按步骤折叠、ANSI 颜色渲染、按日期分组
- 孤儿状态自愈:服务重启后自动校正"卡在构建中"的残留状态(三重存活校验,防 PID 复用误判)
- 构建产物清理:按保留策略清理旧 Release,支持预览,开发版始终保留
- 外部智能体接口:
GET /build-summary供轮询最新状态;/api/help自描述全部 99 个端点
通知与集成
- Webhook 统一管理页:按地址而不是按仓库汇总,一眼看到每个地址被哪些仓库使用、投递成功率、最后投递时间,可一次性从所有引用处移除
- 历史残留地址识别:自动找出"已不在任何配置里、却仍在刷失败记录"的地址(换 IP / 服务下线后的残留),支持逐个或批量清理
- 通知中心:全局聚合投递记录、未读角标、按事件类型静音、桌面系统通知(KDE 等 Linux 桌面实测可用)
- 记录清理:按天数 / 只清失败 / 清空全部,支持按仓库或按地址限定;先预览条数再执行
- 远程同步:一键推送到 Gitee / GitCode / GitHub 等外部远端
权限与运维
- SSH 公钥管理:支持
curl一键提交(/api/ssh-keys/raw) - 部署令牌管理:面向 CI/脚本的访问令牌
- 用户显示名与颜色:按客户端 IP 记录,活动日志中可区分是谁
- 活动日志(审计):全量操作留痕,按日期折叠,可跳转仓库
- 磁盘监控、存储能力探测
- 系统配置:仓库路径、数据路径、全局 Webhook 集中配置
- 一键重启服务(需配置 NOPASSWD sudoers 规则)
工程与质量
- 17 个测试套件、236 个用例:覆盖钩子生成、版本解析、快照降级链、diff 解析、通知水位线、孤儿判定、清理边界等易错路径
- 其中
webhook-api.test.ts会真起服务进程 + 真发 HTTP(隔离临时目录),因为有些缺陷只有跑起来才暴露
- 其中
- 后端核心逻辑抽成无副作用模块,可被测试直接引入
- 99 个 API 端点全部登记进
/api/help,并有测试守护防止漏登 - Vue 3 SPA 前端,GitHub Dark Dimmed 主题,响应式布局
- Nginx 反向代理(关闭缓冲以支持大仓库推送),配置由模板生成、模板本身保持可移植
- systemd 托管:
KillMode=process保证重启面板不会连带杀掉正在跑的构建
这工具适合谁?
| ✅ 适合 | ❌ 不适合 | |--------|----------| | 3-5 人小团队,不想买 GitHub Pro / GitLab 企业版 | 你需要多租户、RBAC 权限管理(请用 GitLab) | | 你在局域网/内网开发,没有公网 IP 和域名 | 你需要 GitHub Actions 的云端并行构建矩阵 | | 你的构建产物很大,想存到外部硬盘/USB | 你需要 Kubernetes + Docker 的容器化 CI | | 你想推送代码后自动构建、自动发版,但不想写 YAML | 你需要复杂的流水线编排(如 Jenkins Pipeline) | | 你的服务器是龙芯/ARM 等特殊架构,主流 CI 不支持 | 你需要 SaaS 托管(如 GitHub Actions、Travis CI) | | 你想秒级备份仓库(btrfs 原生快照 / reflink),硬盘坏了不怕 | 你已经有完善的 DevOps 基础设施 | | 你想让外部智能体/设备通过 Webhook 与构建状态接口接入 | 你的仓库必须放到公网(本项目为可信局域网设计,无鉴权) |
一句话:当你想在自己的局域网里搭一个"够用"的 GitHub,零认证、零数据库、插上硬盘就能跑的时候。
⚠️ 安全边界:面板默认无鉴权,仅供可信局域网使用,不要直接暴露到公网。若需公网访问,请自行在反向代理层加认证与 TLS。
界面预览
以下截图取自真实运行环境(龙芯 loongarch64,浏览器全屏访问 http://192.168.1.64),其中托管着 9 个真实仓库。
落地页 —— 打开面板先看到连接方式与上手说明:三种协议怎么用、怎么建仓库、CI/CD 怎么接

仪表盘 —— 存储路径、磁盘余量、仓库列表与最近活动一屏可见

仓库详情 —— 文件树、README 渲染、分支切换、提交历史;右侧是当前提交的说明

CI/CD 构建历史 —— 按日期分组折叠、今天默认展开;上方是当前构建的步骤与实时状态

Webhook 统一管理 —— 按地址而不是按仓库汇总:谁在用、成功率、最后投递时间,失效地址可从所有引用处一次移除

通知中心 —— 全局聚合投递记录,支持按事件类型静音、桌面系统通知与按条件清理(先预览条数再执行)

项目结构
git-panel/
├── client/ # Vue 3 + TypeScript 前端
│ └── src/
│ ├── components/ # 页面与通用组件(仓库、快照、令牌、Webhook 管理…)
│ ├── extensions/ # 扩展页(构建统计、磁盘监控、代码搜索、通知中心)
│ ├── App.vue
│ └── main.ts
├── server/ # Express + TypeScript 后端
│ ├── server.ts # 主入口(99 个 API 端点)
│ ├── ci-runner.py # CI 编排器(构建、部署、Webhook 投递)
│ ├── hooks-template.ts # post-receive 钩子的唯一权威实现
│ ├── storage-fs.ts # 快照三级降级链与子卷转换
│ ├── diff-engine.ts # 分支/提交 diff
│ ├── webhook-cleanup.ts # 投递记录清理的判定逻辑
│ ├── git-process-reaper.ts # 收割重启遗留的孤儿 git-http-backend
│ ├── deploy-config.ts # 仓库根解析(后端/部署脚本/CI 共用)
│ ├── version.ts # 版本号解析
│ ├── tests/ # 17 个套件、236 个用例
│ └── extensions/ # 扩展路由(构建统计、磁盘、代码搜索)
├── scripts/ # 特权助手(btrfs)与安装脚本
├── web-dist/ # 前端构建产物
├── nginx-full.conf # Nginx 配置模板(含占位符)
├── deploy.sh # 一键部署脚本
└── 版本记录.html # 完整变更历史(含每项的动机与验证方式)快速开始
方式一:npm 全局安装(推荐)
npm install -g @076lik/git-panel
# 启动服务(普通用户)
git-panel
# 自定义端口或仓库路径
git-panel --port=8080 --repo-root=/data/git系统部署(一次性,需要 sudo):
sudo git-panel-deploygit-panel-deploy 会自动完成:环境预检 → 安装依赖 → 编译前后端 → 生成 nginx 配置 → 创建 systemd 服务 → 配置防火墙 → 启动服务。
方式二:源码一键部署
cd /home/lik/git-panel
sudo bash deploy.shdeploy.sh 会自动完成:环境预检 → 安装依赖 → 编译前后端 → 生成 nginx 配置 → 创建 systemd 服务 → 配置防火墙 → 启动服务。
环境变量覆盖(可选):
sudo USER=lik REPO_DIR=/home/lik/git PORT=3456 bash deploy.sh方式三:手动开发模式
如需本地开发调试:
# 后端(ts-node 热重载)
cd server && npm install && npm run dev
# 前端(Vite 热重载)
cd client && npm install && npm run dev仓库存储路径
默认存储在 ~/git,支持通过前端「系统配置」面板修改,保存后点击「重启服务」即可生效(无需手动操作命令行)。
Nginx 与防火墙
deploy.sh 已自动配置。如需手动:
# Nginx
sudo nginx -c /home/lik/git-panel/nginx-full.conf
# 防火墙(firewalld 示例)
sudo firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --add-port=9418/tcp --permanent
sudo firewall-cmd --reload防火墙配置(如需手动)
某些发行版(如 AOSC OS)默认会拒绝 1-1024 端口的入站连接。
图形化方式(AOSC OS):
打开 系统设置 → WiFi 和互联网 → 网络设置 → 防火墙设置 → 在列表中 勾选 http → 点击 确定 → 点击 应用。
命令行方式(firewalld):
# 仅允许局域网(推荐)
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.3.0/24" service name="http" accept'
sudo firewall-cmd --reload
# 全局开放(不推荐暴露在公网)
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --reload连接方式
| 协议 | 地址 | 说明 |
|------|------|------|
| Web 面板 | http://192.168.3.130/ | Nginx 反向代理,标准 80 端口 |
| Git (只读) | git://192.168.3.130/repo.git | git daemon,端口 9418 |
| HTTP (推送) | http://192.168.3.130/api/git/repo.git | Nginx → Node.js 3456 |
| SSH | [email protected]:/run/media/lik/git/repo.git | 标准 22 端口 |
技术栈
- 后端: Node.js 20, Express, TypeScript,
git-http-backendCGI 代理 - 前端: Vue 3, TypeScript, Vite, highlight.js, marked
- 基础设施: Nginx, btrfs/XFS(快照后端自动探测), Git LFS
- 测试: Node 内置断言 + 真实 git 仓库集成测试(无第三方测试框架依赖)
- 工具链:
cloc(语言统计)
语言统计过滤规则
语言统计基于 cloc 计算代码行数,自动排除以下非代码类别:
| 类型 | 被排除的语言 | |------|-------------| | 文档 | Markdown、reStructuredText、TeX、Text | | 配置/数据 | JSON、YAML、XML、TOML、INI、CSV | | 样式 | HTML、CSS、SCSS、Less、Sass | | 构建/脚本 | Dockerfile、Containerfile、Makefile、make、CMake、Gradle、Shell、Bash、PowerShell、Batch | | 其他 | Log、Source Map、SVG |
如果排除后没有剩余语言,则自动回退显示全部结果(避免空列表)。
推送大仓库优化
git config --global pack.windowMemory 512m
git config --global pack.threads 4
git config --global http.postBuffer 2097152000以上为可选的性能调优。需要说明一个曾经的真实缺陷及其修复,避免你再踩:
曾经:pack 体积超过
http.postBuffer(默认仅 1 MiB)时推送必然失败。 超过该阈值后 git 会改用 chunked 传输(无Content-Length),而服务端代理把 环境变量写成了CONTENT_LENGTH: req.headers['content-length'] || '0'—— git 的 receive-pack 在缺Content-Length时是直接报错退出的,'0'等于告诉它「没有请求体」, 于是客户端看到:send-pack: unexpected disconnect while reading sideband packet 致命错误:远端意外挂断了已修复:仅在客户端真的给了
Content-Length时才设置该变量,未给则交由git http-backend按「读到 stdin EOF」处理(这正是 chunked 所需)。 修复后 2.38 MB 的载荷在默认配置下推送成功,包体完整(fsck干净、对象可读)。 回归测试server/tests/git-http-push.test.ts用-c http.postBuffer=1强制走 chunked 路径,已实测可复现该缺陷(还原缺陷代码即变红)。这与仓库大小无关,只与单次推送的 pack 体积有关 —— 纯文本小提交在很大的仓库上 一直都能正常推送,这也解释了为什么它长期难以定位。
测试
后端核心逻辑已抽成无副作用模块,并有回归测试覆盖:
cd server && npm test # 17 个套件,236 个用例| 套件 | 覆盖内容 |
|------|---------|
| post-receive-hook.test.ts | 钩子从 stdin 解析分支、HEAD 自动校正、删除/标签推送不触发构建 |
| version.test.ts | 版本号解析(源码布局 / npm 安装布局 / 兜底) |
| deploy-config.test.ts | 仓库根解析优先级、尾斜杠归一化、配置损坏降级、CLI 输出洁净度 |
| storage-backend.test.ts | 快照三级降级链的判定与命令分派、路径穿越防护、转换失败回滚 |
| ci-liveness.test.ts | CI 孤儿状态判定(三重存活校验、pid 复用防护) |
| diff-engine.test.ts | ref 注入防护、numstat/name-status 解析、改名与二进制边界 |
| notif-read.test.ts | 通知未读水位线语义与边界 |
| notif-prefs.test.ts | 按事件类型静音、桌面通知三重过滤、通知文案 |
| info-page-icons.test.ts | 落地页内联图标与 client/src/icons/index.ts 一致性 |
| api-help-coverage.test.ts | 所有 Express 路由都已登记进 /api/help |
| ci-runner-paths.test.ts | 后端 / deploy.sh / ci-runner.py 三方的路径优先级一致(且后两者复用同一实现) |
| webhook-cleanup.test.ts | 投递历史清理的判定边界(时间缺失一律保留、失败判定、按地址过滤与排除) |
| git-process-reaper.test.ts | 孤儿 git-http-backend 收割的保守判定(后代链、命令行、仓库根三重校验) |
| git-backend-env.test.ts | CONTENT_LENGTH 构造规则(chunked 缺该头时绝不能设成 '0')+ 其余 CGI 变量 |
| git-http-push.test.ts | 真起服务 + 真跑 git push:chunked(大 pack)推送、pack 完整性与 fsck |
| webhook-api.test.ts | 真起服务进程 + 真发 HTTP:统一管理聚合、残留地址识别、清理模式与确认守卫、scope="all" 覆盖全部仓库 |
测试由
npm test自动发现dist/tests/*.test.js—— 新增套件无需改脚本, 避免手工清单漏跑而静默失去保护(api-help-coverage就曾被漏掉)。测试不能继承调用方的 git 上下文(CI 的构建目录本身是裸仓库,会导出
GIT_DIR), 统一通过server/tests/helpers.ts的gitEnv()隔离。验证时可用GIT_DIR=<裸仓库> npm test复现 CI 条件。
作者声明
作者: H076lik
本项目由 H076lik 独立构思、设计并主导开发。所有功能均根据实际局域网 DevOps 需求设计,技术栈(Vue 3 + Express + btrfs/XFS 快照后端 + Python CI Runner)由作者自主决定。
开发过程中使用了 AI 智能体(如 Crush、Claude Code 等)作为代码生成与调试的辅助工具。AI 智能体仅作为开发工具使用,类似于 IDE、编译器等辅助软件,不构成共同创作。所有代码的架构决策、功能设计、逻辑审查、测试验证以及最终知识产权均归属于 H076lik。
赞助名单
如果您觉得本项目对您有帮助,欢迎赞助支持开发。 联系方式与赞助方式待补充...
| 赞助者 | 金额 / 方式 | 日期 | 留言 | |--------|------------|------|------| | 待填写 | — | — | — |
许可证
本项目采用 GNU Lesser General Public License v3.0 (LGPL-3.0) 开源许可。
- 核心源码(
client/src/、server/、配置文件及部署脚本)均已在文件头部添加 LGPL-3.0 标准声明 - 允许商用、修改与再分发,但修改后的库文件需以相同许可证开源
- larger work(调用本平台的应用程序)可独立使用不同许可证,无需强制开源
- 完整许可证文本见仓库根目录
LICENSE文件
法律说明:本项目为独立实现的 Git 仓库与 CI/CD 管理平台。功能接口与 DevOps 流程参考了开源社区(包括 GitHub、GitLab)的成熟实践,但全部代码由 H076lik 独立编写。
Copyright (C) 2025-2026 H076lik
CI/CD 完整指南
Git Panel 内置完整的持续集成/持续部署流水线,支持自动构建、部署和外部通知。
CI 流水线(自动构建)
推送代码后自动触发:
- 检出代码到
deploy/{repo} - 执行配置的构建步骤(如
npm run build、cargo build、go test) - 支持自动检测项目类型(Rust/Go/TypeScript/Python/C/C++/Java/Lua)
- 自动识别
.github/workflows/*.yml和.gitlab-ci.yml - CI 配置工作流化:手动配置的构建步骤保存为
.github/workflows/git-panel-ci.yml并自动git commit,配置与代码一起版本控制 - 自动发布起始版本号:Dev Release 支持设置起始版本号(如
2.0.0),自动递增v2.0.1→v2.0.2
CD 持续部署
构建成功后自动执行部署步骤:
- 在 CI 配置中勾选「构建成功后自动部署」
- 添加部署命令(如
cp target/release/app /opt/bin/) - 支持手动触发
POST /api/repos/{name}/deploy
Webhook 通知
构建/部署完成后向局域网内其他设备/智能体发送 HTTP POST 通知:
# 配置 Webhook(前端 CI/CD → 配置 Webhook)
# 或使用 API
POST /api/repos/{name}/webhook
{
"enabled": true,
"url": "http://192.168.3.xxx:8080/webhook",
"events": ["build.failed", "build.success", "deploy.failed", "deploy.success"]
}推送内容示例:
{
"event": "build.failed",
"repo": "YouLiLong",
"branch": "master",
"commit": "c993fe94...",
"commitMsg": "refactor(dap): ...",
"runId": "1778663640",
"status": "failed",
"steps": [{"name": "Build release", "status": "failed"}],
"timestamp": "2026-05-13T17:34:00",
"server": "git-panel"
}构建摘要 API(外部智能体查询)
GET /api/repos/{name}/build-summary返回示例:
{
"repo": "YouLiLong",
"ci": {
"status": "success",
"runId": "1778665915",
"branch": "master",
"commit": "13aa0970...",
"duration": 8,
"steps": [{"name": "Build Client", "status": "success"}],
"deployStatus": "success"
},
"deploy": {
"status": "success",
"runId": "1778665915"
},
"lastUpdated": "2026-05-13T17:52:03Z"
}CI 日志折叠与 ANSI 颜色
- 构建日志按步骤自动折叠(▶/▼ 切换)
- ANSI 颜色转义码自动转换为 HTML 颜色(红/绿/黄等)
- 实时轮询更新(3秒间隔)
Python 项目 UV 支持
检测到 uv.lock 或 pyproject.toml 中包含 tool.uv 时自动使用 uv sync:
{"steps": [
{"name": "UV Sync", "command": "uv sync || uv pip install -e . || true"},
{"name": "Test", "command": "uv run pytest || true"}
]}