# git-go **Repository Path**: zhReimu/git-go ## Basic Information - **Project Name**: git-go - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-04 - **Last Updated**: 2026-07-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # git-go · 自托管 Git 服务器 > 基于 **Go 1.26 + Echo v5 + Vue 3 + UnoCSS** 构建的轻量级自托管 Git 服务,前端构建产物通过 `go:embed` 嵌入二进制,单文件部署。 ## ✨ 特性 ### 用户与权限 - **多用户系统**:管理员可创建/禁用/删除用户,**不允许自助注册** - **个人资料管理**:用户可自助修改头像(base64 存 DB)、用户名、邮箱、密码 - **头像菜单**:右上角头像点击展开下拉菜单(个人设置 / 退出登录) - **权限模型**:私有仓库仅 owner 与管理员可访问;推送需 HTTP Basic Auth 或 SSH 公钥认证 ### 仓库管理 - **仓库 CRUD**:创建、编辑、删除、可见性控制(公开/私有) - **文件管理**:浏览文件树、查看文件内容、**Monaco Editor 在线编辑**(支持多语言语法高亮) - **README 预览**:自动渲染 README.md(marked + GFM) - **分支列表**:展示所有分支与默认分支 - **设置 Tab**:基本信息编辑、镜像仓库配置、危险操作区 ### Git 协议 - **HTTP/HTTPS 克隆**:基于 `git http-backend` 实现智能协议,支持匿名 clone 公开仓库 - **SSH 克隆**:基于 `crypto/ssh` 自实现 SSH 服务器,用户自助管理公钥,按公钥指纹映射用户身份 - **Push 版本反馈**:push 后客户端显示 `Powered by git-go `(通过 post-receive hook) ### 镜像仓库 - **自动同步**:启用后,对本仓库的推送操作(push、tag)自动同步到下游仓库 - **多鉴权**:支持 none / basic / ssh 三种鉴权方式 - **失败提示**:同步失败时仓库首页显示红色横幅(含错误原因) ### 系统配置 - **system_settings 表**:存储系统级配置(SSH host key、是否允许注册等) - **SSH host key 存 DB**:不再依赖文件,重启不丢失 - **日志可配置**:CLI > 环境变量 > 配置文件,默认 INFO,静态资源请求自动降级到 DEBUG - **配置优先级**:CLI 参数 > 环境变量(GITGO_ 前缀)> YAML 配置文件 > 内置默认值 ### UI 设计 - **Material Design 3 风格**:Vue 3 + UnoCSS 实现的质感设计界面 - **设计工程化**:完整的 [设计规范文档](docs/DESIGN.md)(设计 token、组件规范、交互规范) - **自定义组件库**:BaseDialog / BaseCheckbox / EmptyState / MonacoEditor 等,禁止使用浏览器原生组件 - **离线可用**:无 CDN 依赖,前端资源全部通过 go:embed 嵌入二进制 ## 🏗️ 技术栈 | 层 | 技术 | |------|------| | 后端框架 | [Echo v5](https://github.com/labstack/echo) v5.2.1 | | 数据库 | SQLite([glebarez/sqlite](https://github.com/glebarez/sqlite) 纯 Go 驱动,无需 CGO) | | ORM | [GORM](https://gorm.io) v2 | | 鉴权 | JWT ([golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt)) + bcrypt | | Git 操作 | 通过 `GitOperator` 接口抽象,当前用本地 `git` 命令实现([LocalGitOperator](internal/repo/local_git.go)) | | Git HTTP | 系统 `git http-backend` (CGI 桥接) | | Git SSH | [crypto/ssh](https://pkg.go.dev/golang.org/x/crypto/ssh) 自实现 | | 前端框架 | Vue 3.5 + Vue Router 5 + Pinia 3 + Axios | | 前端样式 | [UnoCSS](https://unocss.dev) 66.x + Material Design 3 token | | 代码编辑器 | [Monaco Editor](https://microsoft.github.io/monaco-editor/)(Vite 集成,离线可用) | | Markdown 渲染 | [marked](https://marked.js.org/)(GFM 支持) | | 图标 | @iconify-json/mdi + @iconify-json/material-symbols | | 构建工具 | Vite 7 + vue-tsc 3 | ## 📁 目录结构 ``` git-go/ ├── cmd/ │ └── server/ │ └── main.go # 程序入口 ├── internal/ │ ├── config/ # 配置加载(CLI > env > YAML > 默认) │ ├── model/ # 数据模型(User/Repository/SSHKey/RepoMirror/SystemSetting) │ ├── store/ # SQLite + GORM 持久化层 │ ├── auth/ # JWT 签发/校验 + bcrypt 密码哈希 │ ├── settings/ # system_settings 表读写服务 │ ├── version/ # 版本信息(ldflags 注入) │ ├── repo/ # Git 仓库操作(接口抽象) │ │ ├── operator.go # GitOperator 接口定义 │ │ ├── local_git.go # LocalGitOperator(本地 git 实现) │ │ ├── manager.go # Manager(路径管理 + 委托 operator) │ │ └── mirror.go # MirrorManager(镜像同步) │ ├── service/ # 业务编排层(用户/仓库/SSH Key/镜像 CRUD) │ ├── handler/ # HTTP 路由处理器 │ │ ├── handler.go # 鉴权中间件 + 路由注册 │ │ ├── api.go # 业务 API │ │ ├── git_http.go # Git HTTP 智能协议桥接 │ │ └── static.go # 前端静态资源服务 │ ├── gitssh/ # Git SSH 服务器 │ └── embeddist/ # go:embed 嵌入前端产物 ├── frontend/ # Vue 3 前端源码 │ ├── src/ │ │ ├── views/ # 7 个视图 │ │ ├── components/ # 通用组件(含 MonacoEditor/ReadmePreview/UserMenu) │ │ ├── api/ # axios 封装 │ │ ├── stores/ # Pinia store │ │ ├── router/ # 路由配置 + 鉴权守卫 │ │ └── styles/ # 全局样式 │ ├── package.json │ ├── vite.config.ts # 构建输出到 ../internal/embeddist/dist │ ├── uno.config.ts # Material Design 3 主题 token │ └── tsconfig.json ├── docs/ │ └── DESIGN.md # UI 设计规范文档 ├── go.mod └── README.md ``` ## 🔧 架构设计:GitOperator 接口抽象 所有 Git 仓库操作通过 `GitOperator` 接口抽象,调用方只依赖接口,不依赖具体实现: ```go // internal/repo/operator.go type GitOperator interface { InitBare(owner, name, defaultBranch string) error Remove(owner, name string) error Exists(owner, name string) bool ListBranches(owner, name string) ([]string, error) LastCommitInfo(owner, name, branch string) (*LastCommit, error) ListTree(owner, name, branch, path string) ([]FileEntry, error) FileContent(owner, name, branch, path string) (string, bool, error) ReadmeContent(owner, name, branch string) (string, string, error) SaveFile(owner, name, branch, path, content, message, authorName, authorEmail string) error PushMirror(ctx context.Context, owner, name, remoteURL string, authInfo *MirrorAuth) error } ``` 当前实现:`LocalGitOperator`(基于本地 `git` 命令行)。未来可用纯 Go 实现(如 go-git)替换,只需实现接口,无需改动调用方。 ## 🚀 快速开始 ### 1. 构建 ```bash # 构建前端(输出到 internal/embeddist/dist) cd frontend && npm install && npm run build && cd .. # 构建后端(嵌入前端产物,生成单文件二进制) # 版本号通过 ldflags 注入 CGO_ENABLED=0 go build -ldflags "-X git-go/internal/version.Version=v1.0.0" -o git-go ./cmd/server ``` ### 2. 启动 ```bash # 最简启动(默认管理员 admin/admin) ./git-go --http-addr :3000 --ssh-addr :2222 --data-dir ./data # 生产启动 ./git-go \ --http-addr :3000 \ --ssh-addr :2222 \ --data-dir /var/lib/gitgo \ --secret "$(openssl rand -hex 32)" \ --admin-name admin \ --admin-password "your-strong-password" \ --log-level info ``` ### 3. 使用配置文件 ```yaml # config.yaml http_addr: ":3000" ssh_addr: ":2222" data_dir: "/var/lib/gitgo" secret: "your-jwt-secret" log_level: "info" # debug / info / warn / error admin: name: "admin" password: "admin" email: "admin@localhost" ``` ```bash ./git-go --config /etc/gitgo/config.yaml ``` ## ⚙️ 配置参考 配置优先级从高到低:**CLI 参数 > 环境变量 > YAML 配置文件 > 内置默认值**。 ### CLI 参数 | 参数 | 说明 | 默认值 | |------|------|--------| | `--config` | YAML 配置文件路径 | `./config.yaml` | | `--http-addr` | HTTP 监听地址 | `:3000` | | `--ssh-addr` | SSH 监听地址 | `:2222` | | `--data-dir` | 数据目录 | `./data` | | `--secret` | JWT 签名密钥 | 内置默认(生产必改) | | `--admin-name` | 初始管理员用户名 | `admin` | | `--admin-password` | 初始管理员密码 | `admin` | | `--admin-email` | 初始管理员邮箱 | `admin@localhost` | | `--log-level` | 日志等级:debug/info/warn/error | `info` | ### 环境变量 所有 CLI 参数均有对应的环境变量,前缀为 `GITGO_`: | 环境变量 | 对应 CLI 参数 | |----------|---------------| | `GITGO_HTTP_ADDR` | `--http-addr` | | `GITGO_SSH_ADDR` | `--ssh-addr` | | `GITGO_DATA_DIR` | `--data-dir` | | `GITGO_SECRET` | `--secret` | | `GITGO_LOG_LEVEL` | `--log-level` | | `GITGO_ADMIN_NAME` | `--admin-name` | | `GITGO_ADMIN_PASSWORD` | `--admin-password` | | `GITGO_ADMIN_EMAIL` | `--admin-email` | ### 日志说明 - 默认 INFO 级别,静态资源请求(`/`、`/favicon.svg`、`/assets/*`)自动降级到 DEBUG 不打印 - 设为 `debug` 后会打印所有请求日志(含静态资源) - 日志格式为 JSON,包含 time/level/msg + 结构化字段 ## 📦 仓库克隆 ### HTTP 克隆 ```bash # 公开仓库(匿名 clone) git clone http://your-host.com/owner/repo.git # 私有仓库 git clone http://owner@your-host.com/owner/repo.git ``` ### SSH 克隆 1. 在 Web UI 「SSH 公钥」页面添加你的 `~/.ssh/id_ed25519.pub` 2. 克隆: ```bash git clone ssh://git@your-host.com:2222/owner/repo.git ``` ## 🔐 权限模型 | 操作 | 公开仓库 | 私有仓库 | |------|----------|----------| | 匿名 clone | ✅ | ❌ | | 已登录用户 clone | ✅ | ✅(仅 owner / 管理员) | | HTTP push | 需 Basic Auth | 需 Basic Auth(owner / 管理员) | | SSH push | 需 SSH Key(owner / 管理员) | 需 SSH Key(owner / 管理员) | | 在线编辑文件 | owner / 管理员 | owner / 管理员 | ## 🛡️ 安全设计 - **密码哈希**:bcrypt cost=10,永不存储明文 - **JWT 鉴权**:HS256 签名,24 小时有效期 - **路径穿越防护**:所有仓库路径通过 `ResolveSafePath` 校验 - **SSH 命令白名单**:SSH exec 请求只允许 `git-upload-pack` 与 `git-receive-pack` - **Git 安全配置**:所有新建仓库自动设置 `receive.denyNonFastforwards=true` 与 `receive.denyDeletes=true` - **SSH host key 存 DB**:不依赖文件系统,重启不丢失 - **管理员保护**:不允许删除自己 / 最后一个启用的管理员 ## 🔌 API 一览 所有 API 位于 `/api` 前缀下,除 `/api/health` 与 `/api/login` 外均需 `Authorization: Bearer `。 | 方法 | 路径 | 说明 | 权限 | |------|------|------|------| | `GET` | `/api/health` | 健康检查 | 公开 | | `POST` | `/api/login` | 登录获取 JWT | 公开 | | `GET` | `/api/me` | 获取当前用户 | 已登录 | | `PATCH` | `/api/profile` | 修改个人资料(头像/用户名/密码) | 已登录 | | `GET/POST` | `/api/repos` | 列出/创建仓库 | 已登录 | | `GET/PATCH/DELETE` | `/api/repos/:owner/:repo` | 仓库详情/编辑/删除 | 已登录 | | `GET` | `/api/repos/:owner/:repo/branches` | 分支列表 | 已登录 | | `GET` | `/api/repos/:owner/:repo/last-commit` | 最近提交 | 已登录 | | `GET` | `/api/repos/:owner/:repo/tree` | 文件树 | 已登录 | | `GET/POST` | `/api/repos/:owner/:repo/file` | 读取/编辑文件 | 已登录 | | `GET` | `/api/repos/:owner/:repo/readme` | README 内容 | 已登录 | | `GET/PUT` | `/api/repos/:owner/:repo/mirror` | 镜像配置 | 已登录 | | `GET/POST/DELETE` | `/api/ssh-keys[/:id]` | SSH 公钥管理 | 已登录 | | `GET/POST/PATCH/DELETE` | `/api/admin/users[/:id]` | 用户管理 | 管理员 | | `GET/POST` | `/:owner/:repo.git/info/refs` | Git HTTP 智能协议 | 按仓库权限 | | `POST` | `/:owner/:repo.git/git-upload-pack` | Git HTTP fetch | 按仓库权限 | | `POST` | `/:owner/:repo.git/git-receive-pack` | Git HTTP push | 按仓库权限 | ## 🧪 开发模式 ### 前后端分离开发 ```bash # 终端 1:启动后端 go run ./cmd/server --http-addr :3000 # 终端 2:启动前端 dev server(自动代理 /api 到 3000) cd frontend && npm run dev ``` 浏览器访问 `http://localhost:5173`。 ### 生产构建 ```bash cd frontend && npm run build && cd .. CGO_ENABLED=0 go build -ldflags "-X git-go/internal/version.Version=v1.0.0" -o git-go ./cmd/server ``` ## 📜 许可证 MIT License