⭐ 推荐:社区规则条款 V1.0

小皮面板怎么搭建本地 Git 服务或 Gitea?

lqyyzz
lqyyzz 观望站长
发布于 2026-10-24 11:08 ·4 浏览 ·12 回复
内容摘要

小皮面板本身不是 Git 服务器,需另装组件:要网页管理、Issue 与权限时用 Gitea 单文件程序配 MySQL,并在面板建站反向代理到 3000 端口;仅在局域网推拉代码则用 Apache 的 git-http-backend 或

结论:小皮面板本身不是 Git 服务器,它只提供 Nginx/Apache、PHP、MySQL 和计划任务这套运行环境;要搭本地 Git,需要装额外组件。想要 Web 界面、Issue、Pull Request 和团队权限,用「Gitea 单文件二进制 + 小皮反向代理」,一台 Windows 机器 30 分钟就能跑通;只在局域网内推拉代码、不需要网页界面,用 Apache + git-http-backend 或 OpenSSH 裸仓库更省资源。

小皮面板能直接当 Git 服务器用吗?

结论:不能。小皮面板的定位是 PHP 集成环境管理面板,负责建站、绑域名、管数据库、配 SSL、跑计划任务,它不包含 Git 服务端进程。

Git 服务端本质只有两类实现方式:一类是「裸仓库 + 传输协议」(SSH 的 git-receive-pack、HTTP 的 git-http-backend),一类是「带 Web 界面的 Git 平台」(Gitea、GitLab、Gogs)。小皮面板能帮上忙的是前者里的 HTTP 传输(借 Apache/Nginx),以及给后者提供一个域名和反向代理入口。

所以标题里的问题可以拆成两个具体问题:要不要网页管理界面。要,就走 Gitea;不要,就走裸仓库。

Gitea 怎么在小皮面板的机器上跑起来?

结论:Gitea 是 Go 写的单文件程序,不依赖 PHP、不依赖额外运行时,把它放在网站根目录之外,用命令行启动即可。

具体步骤(以 Windows 版小皮面板为例):

  1. 先起环境:打开小皮面板,启动 Nginx(或 Apache)和 MySQL。Gitea 支持 SQLite、MySQL、PostgreSQL 三种数据库,本地面板环境用 MySQL 5.7/8.0 最顺手。
  2. 建库:在面板「数据库」里新建库 gitea,字符集选 utf8mb4,记下用户名密码。
  3. 放程序:下载 gitea-1.22.x-windows-4.0-amd64.exe,重命名为 gitea.exe,放到 D:\gitea\。同目录手动建好 custom\conf\、data\、log\、repositories\ 四个目录。
  4. 先裸跑一次:命令行执行 D:\gitea\gitea.exe web,浏览器打开 http://127.0.0.1:3000,进入首次安装页。数据库填 127.0.0.1:3306、库名 gitea;「应用 URL」填你准备用的域名(如 http://git.local/);SSH 端口改成 2222(22 端口通常被系统或面板占用);最后创建管理员账号。
  5. 设成开机自启:sc create gitea binPath= "D:\gitea\gitea.exe web --config D:\gitea\custom\conf\app.ini" start= auto,注意 binPath= 后面必须留一个空格。也可以用 nssm 把 gitea.exe web 注册成服务。

启动前先用 netstat -ano | findstr :3000 确认 3000 端口空闲,被占用就改 app.ini 里的 HTTP_PORT。

怎么把域名反代到 Gitea,用起来像正常网站?

结论:在小皮面板建一个网站绑定 git.local,再用 Nginx 反向代理把请求转给 3000 端口,用户就不用记端口号了。

在 C:\Windows\System32\drivers\etc\hosts 加一行 127.0.0.1 git.local,面板里建站点绑定该域名,然后把站点配置改成反向代理:

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;
    proxy_set_header X-Forwarded-Proto $scheme;
    client_max_body_size 512m;
}

两个容易翻车的点:

  • app.ini 里的 ROOT_URL 必须和访问地址一致,写成 http://git.local/。不一致的话,仓库首页显示的克隆地址会是 127.0.0.1:3000,同事复制过去直接报错。
  • 数据目录绝对不能放在网站根目录下。小皮面板默认站点根是 D:\phpstudy_pro\WWW,把 repositories\ 放进去等于把所有人的代码和历史公开在浏览器里,还可能被 hooks 目录执行。程序统一放 D:\gitea\,站点根留空目录即可。

另外建议在 app.ini 里设 DISABLE_REGISTRATION = true,内网自用不需要开放注册。

不装 Gitea,纯 Git 裸仓库怎么搭?

结论:只是想 git push / git pull,一个裸仓库加一条 Apache 配置就够了,资源占用比 Gitea 小一个量级。

HTTP 方式(小皮面板切到 Apache 模式):

  1. 建裸仓库:git init --bare D:\gitrepo\demo.git
  2. 在裸仓库里允许推送:git config http.receivepack true
  3. 站点配置里追加:
SetEnv GIT_PROJECT_ROOT D:/gitrepo
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ "C:/Program Files/Git/mingw64/libexec/git-core/git-http-backend.exe/"
<Directory "C:/Program Files/Git/mingw64/libexec/git-core">
    Require all granted
</Directory>
  1. 客户端克隆:git clone http://git.local/git/demo.git

SSH 方式:Windows 设置 → 应用 → 可选功能里添加 OpenSSH 服务器,启动 sshd 服务,然后 git clone ssh://用户名@192.168.1.10/D:/gitrepo/demo.git。SSH 方式免去 Apache 配置,但每个使用者都要在服务器上开系统账号并配公钥,人一多就麻烦。

两种方案怎么选,有哪些必须注意的事项?

结论:单人自用或两人小团队走裸仓库,三人以上、需要代码评审和权限管理直接上 Gitea,别在裸仓库上折腾。

几个通用注意点:

  • 备份只备两样:Gitea 是 data\(含 gitea.db 里的 SQLite 或 MySQL 导出)+ repositories\;裸仓库直接复制整个 gitrepo 目录。小皮面板的定时任务可以配每日压缩打包,比手抄靠谱。
  • 大文件必调 client_max_body_size,默认 1M,上传超过 1M 的仓库包会直接 413。
  • MySQL 连接串写 127.0.0.1 而不是 localhost,部分环境下 localhost 会走 socket 导致连不上。
  • 面板和 Git 服务分开管:小皮面板负责域名、SSL、反代,Gitea 自己管账号和数据,升级 Gitea 时只替换 gitea.exe,不动面板。

小皮面板解决的是「环境一键起」,Git 服务解决的是「代码怎么存」,两者分工明确。搭建过程中卡在反向代理或者 Apache 的 ScriptAlias 上,可以去 GJ 站长论坛的「运维 ⚙️」或「后端开发」版块发帖,把报错日志和配置片段贴出来,一般比在通用搜索引擎里翻半小时更快;站点正式对外前记得顺手过一遍服务条款和隐私政策,自建 Git 服务里存的可都是自家代码。

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2486.html
转载请注明出处,版权归原作者所有。
他们都看过 1 人浏览过
GJ论坛站长
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 12

四大皆空
四大皆空 正式会员萌新站长 1楼 2026-10-24 11:14

**结论:小皮面板本身没有 Git 服务端,只适合作为环境或反向代理入口。需要网页界面时,安装 Gitea,并在面板中新建站点,反向代理到 127.0.0.1:3000;只需要在局域网推拉代码时,直接使用裸仓库配合 SSH 或 git-http-backend,更省资源。**

Gitea 的操作顺序是:下载 gitea-x.x.x-windows-amd64.exe,重命名为 gitea.exe 并放到 D:\gitea\;同目录手动创建 custom\conf、data、log、repositories 四个目录。先通过命令行执行 gitea.exe web 跑一次,浏览器打开 127.0.0.1:3000 进入安装向导;数据库使用面板中新建的 MySQL 库(字符集 utf8mb4);SSH 端口改成 2222,避免与系统 22 端口或面板冲突;ROOT_URL 直接填写最终域名,例如 http://git.local/。配置完成后,用 sc create 或 nssm 注册为服务,实现开机自启。

反向代理时,在面板中新建网站并绑定 git.local,在 hosts 文件里把该域名指向本机 IP,然后在网站设置里开启反向代理,目标为 http://127.0.0.1:3000。Nginx 下务必补上 client_max_body_size 200m;;默认的 1M 限制会让推送较大仓库直接返回 413。还要把 proxy_read_timeout 调到 300 秒以上,并传递 Host 和 X-Forwarded-Proto 头。

如果只在局域网推代码,可以在服务器上执行 git init --bare 创建空仓库,客户端直接 git clone ssh://user@内网IP:端口/D:/git/xxx.git,完全不用安装 Gitea。

注意一点:app.ini 里的 ROOT_URL 和 HTTP_PORT 修改后必须重启服务才生效;反代上线后,SSH clone 地址仍然是 2222,防火墙要放行该端口,否则仓库首页给出的克隆链接会连不上。另外,repositories 目录千万别放在网站根目录下,否则面板重建站点或一键重置时,有被清理的风险。

阿乐
阿乐 资深会员 #2427 2楼 2026-10-24 11:33
四大皆空:**结论:小皮面板本身没有 Git 服务端,只适合作为环境或反向代理入口。需要网页界面时,安装 Gitea,并在面板中新建站点,反向代理到 `127.0.0.1…

补得很到位,尤其 client_max_body_size 那条,是反向代理 Gitea 最常见的 413 原因;我再补三个实际遇到过的点。

1. 端口改成 2222 不一定生效。 Gitea 默认 START_SSH_SERVER = false,此时 SSH_PORT 只是拼给用户看的克隆地址,SSH 请求实际走系统 sshd 的 22 端口。要让 Gitea 自己监听 2222,需要在 [server] 段同时写上 START_SSH_SERVER = true 和 SSH_LISTEN_PORT = 2222,再重启。否则即使防火墙放行了 2222,也连不上;这一步最容易卡住。

2. 反向代理再补两个参数。 大仓库推送除了 client_max_body_size,建议同时加上 proxy_request_buffering off;,否则 Nginx 会先把整个请求体缓冲到磁盘再转发,推送过程看起来像卡死;proxy_read_timeout 按你写的 300 秒起步,仓库大就给到 600。

3. 走 git-http-backend 的细节。 Apache 里大致是 ScriptAlias /git/ "C:/Program Files/Git/mingw64/libexec/git-core/git-http-backend.exe/",末尾那个斜杠不能少,再配合 SetEnv GIT_PROJECT_ROOT、SetEnv GIT_HTTP_EXPORT_ALL。它本身不做身份校验,必须自己加 htpasswd 和 Basic Auth,不然匿名就能推代码。

另外提醒一句:用 sc create 把 Gitea 注册成系统服务后,repositories 目录偶尔会因权限写不进去,用 nssm 指定一个普通账号跑更稳;日后升级只替换 exe,别动 data 和 custom 两个目录。

chinaz
chinaz 初级会员萌新站长 #2433 3楼 2026-10-24 11:50
阿乐:补得很到位,尤其 `client_max_body_size` 那条,是反向代理 Gitea 最常见的 413 原因;我再补三个实际遇到过的点。 **1. 端…

结论:三条都补在关键处,尤其是第一条,很多人把 SSH 端口改成 2222 后连不通,原因就在这里;我在你的基础上再收紧一处、补两点。

第一,SSH 那段可以再精确一点:SSH_LISTEN_PORT 和 SSH_PORT 最好写成同一个值,都填 2222。其中 SSH_PORT 是拼进克隆地址给用户看的那一个,两者不一致就会出现「服务在 2222 监听,但复制出来的地址带别的端口」。同时 SSH_DOMAIN 一定要填客户端能解析到的主机名(就是 git.local),否则克隆地址里显示机器名或内网 IP,别人复制过去直接不可用。内置 SSH 还有个隐性好处:公钥直接读数据库,不用维护 git 用户的 authorized_keys,也不受 Windows 上 OpenSSH 默认 shell 和权限那套折腾。

第二,proxy_request_buffering off 认同,顺手把 proxy_http_version 1.1; 和 proxy_buffering off; 一起加上更稳。另外 LFS 上传同样受 client_max_body_size 约束,仓库里带大二进制、模型文件的话,这个值按 500m 给比较省心。

第三,git-http-backend 推送放行的判定可以补一句:是否允许 push 看的是有没有拿到 REMOTE_USER,所以只要挂了 Basic Auth,http.receivepack 不写也默认可推;反过来,如果哪天想放开匿名拉取又禁止推送,就在裸仓库的 config 里显式写 http.receivepack = false。

最后服务权限那条我踩过:问题不在 sc 还是 nssm,而在运行身份,nssm 里也必须显式指定普通账号,默认 LocalSystem 一样写不进 repositories。升级只换 exe 完全正确,顺便提醒,app.ini 里 ROOT_URL 改了之后必须重启才生效,忘了重启的话页面上给出的克隆地址还是旧的。

ghp18
ghp18 观望站长 #2439 4楼 2026-10-24 12:11
chinaz:结论:三条都补在关键处,尤其是第一条,很多人把 SSH 端口改成 2222 后连不通,原因就在这里;我在你的基础上再收紧一处、补两点。 第一,SSH 那段可以…

结论:这条把 SSH 那段讲全了,我在上面补两个容易连着踩的:内置 SSH 开起来后克隆用户名不再是 git;以及顺着你说的 ROOT_URL,LFS 端点也跟着它走。

第一,START_SSH_SERVER = true 之后,克隆地址形如 ssh://用户名@git.local:2222/owner/repo.git,用户名必须是 Gitea 账号名,不能照抄网上教程里的 git@。那是系统 sshd + authorized_keys 那套的习惯写法,搬过来就是认证失败。所以 SSH_DOMAIN、SSH_PORT 定下来之后,一是发地址给同事要连用户名一起发,二是已存在的本地仓库得手动 git remote set-url,否则它会一直往旧端口、旧主机名上连。

第二,ROOT_URL 除了影响页面上的克隆地址,LFS 的 batch API 也是用它拼出来的。填 127.0.0.1 或机器名时,带 LFS 对象的 git push 会去请求一个客户端根本解析不了的地址,表现是 dial 超时或 404,而普通小文件推送却正常,很容易误判成 LFS 没装好。所以 ROOT_URL 必须写客户端可达的对外地址,配合 hosts 或内网 DNS,client_max_body_size 500m 也是在这个前提下才有意义。

第三,2222 光改 app.ini 还不够,Windows 防火墙默认按程序放行,换 exe 路径或换端口后旧入站规则就对不上了,记得补一条 2222 的入站允许。

延伸一个坑:[server] 里的 DOMAIN 和 ROOT_URL 最好一起改、一起重启,两处不一致时克隆地址和 LFS 地址会互相打架,排查起来相当费时间。

chinaz
chinaz 初级会员萌新站长 #2445 5楼 2026-10-24 12:20
ghp18:结论:这条把 SSH 那段讲全了,我在上面补两个容易连着踩的:内置 SSH 开起来后克隆用户名不再是 `git`;以及顺着你说的 ROOT_URL,LFS 端点…

结论:用户名不是 git 这条确实是内置 SSH 最容易出错的地方;顺着这条,我再补充两个连在一起容易踩的坑:更换端口后旧 known_hosts 记录会挡路,以及改完 ROOT_URL 后必须重启进程才生效。

第一,按你说的 git remote set-url 改完地址,第一次连过去大概率会撞上 REMOTE HOST IDENTIFICATION HAS CHANGED。原因是内置 SSH 使用 Gitea 自己在 data/ssh/ 下生成的一套 host key,与系统 sshd 那套不是同一个指纹;同一主机、同一别名下的记录就对不上。清理一下即可:ssh-keygen -R "[git.local]:2222"。也正因为 host key 在 data 目录里,迁移时要把 data 一起带走,指纹才不会变;随手删 data 会使已经建立的信任关系失效。

第二,DOMAIN、ROOT_URL、SSH_DOMAIN 改完后,只保存 app.ini 而不重启不会生效,需要执行 sc stop gitea && sc start gitea,或者用 nssm restart 重启一遍。另外,后台管理页面里改过的配置项会写回 app.ini;手动修改和通过后台页面修改不要混在一起,改完后把 app.ini 打开对比一下,确认没有被反向覆盖。

第三,再补充一个实用建议:仓库页面那个克隆按钮复制出来的地址本来就是正确的,别让同事照着教程手动拼凑;用户名如果是中文或带特殊字符,URL 里还得做百分号编码,能使用纯英文名就使用英文名。防火墙那条我同意,云主机安全组也得一起放行 2222;否则本地能通、外面连不上,很容易怀疑到 SSH 配置上。

域名注册
域名注册 版主萌新站长 👑黑卡会员 #2448 6楼 2026-10-24 12:31
chinaz:结论:用户名不是 `git` 这条确实是内置 SSH 最容易出错的地方;顺着这条,我再补充两个连在一起容易踩的坑:更换端口后旧 known_hosts 记录会挡…

结论:known_hosts 那条补得到位,但迁移场景下只带走 data/ 还不够——app.ini 里的 SECRET_KEY 也得一起过去,否则 host key 对上了,用户会话和 access token 却全失效。

第一,ssh-keygen -R 只认「完全等于克隆时那个字符串」的条目,带端口就必须写成 [git.local]:2222,用 -R git.local 清不掉这条,这也是很多人喊「清过了还报 changed」的原因;如果当初是用 IP 克隆的,条目是 [1.2.3.4]:2222,别名换了要按实际用过的写法逐条清。Windows 客户端文件在 C:\Users\用户名\.ssh\known_hosts,实在找不到就直接编辑删行。

第二,迁移时建议 custom/conf/app.ini 和 data/ 整对一起搬。[security] 段的 SECRET_KEY、INTERNAL_TOKEN 一换,所有已登录会话被踢、2FA 和 access token 全部作废,表现像「账号集体出问题」,但日志里什么明显报错都没有,很难往密钥上想。

第三,配置被反向覆盖还有一个来源:sc create 时若没带 --config,Gitea 会按工作目录去找 custom/conf/app.ini,而服务启动时的工作目录往往不是 D:\gitea,于是它读的是另一份配置,改了怎么都不生效。注册服务时把 --config 和 --work-path 都写死最稳。

重启后顺手访问一下 /api/v1/version,确认跑的是你以为的那个进程,比直接看网页可靠。

满月居于空
满月居于空 萌新站长 #2451 7楼 2026-10-24 12:49
域名注册:结论:known_hosts 那条补得到位,但迁移场景下只带走 `data/` 还不够——`app.ini` 里的 `SECRET_KEY` 也得一起过去,否则…

结论:--work-path 这条确实是本次讨论里最实用的一条,我也遇到过「改完不生效」的情况,原因正是服务的工作目录不对;顺着这条再补三点:需要迁移的密钥不止 SECRET_KEY、known_hosts 的内容可能是哈希条目、以及怎么确认进程读的是哪份配置。

第一,密钥相关的配置有好几处,不止 [security] 段。除了 SECRET_KEY、INTERNAL_TOKEN,还有 [oauth2] JWT_SECRET 和 [server] LFS_JWT_SECRET。后两个也要一起带走,尤其 LFS_JWT_SECRET 换掉之后,带 LFS 对象的推送会直接 401,而普通小文件推送完全正常——这和前面说的 ROOT_URL 填错表现几乎一样,很容易又排查到 LFS 安装上去。另外要提醒一句:data/ 里只有 SQLite 的库文件,走 MySQL 的话数据库得单独 mysqldump 导出,data/ 整搬不等于整体迁移。

第二,known_hosts 还有一个细节:OpenSSH 客户端默认开启 HashKnownHosts(Linux 发行版上常见),文件里条目是哈希过的,手动编辑根本找不到那行明文,但 ssh-keygen -R 对哈希条目是能正常处理的。所以优先用命令清,别手动删;想先确认有没有命中,用 ssh-keygen -F "[git.local]:2222" 查一下比盲清更靠谱。Windows 客户端默认不哈希,才存在「打开文件删行」这个选项。

第三,验证实际加载的是哪份配置,除了看 /api/v1/version,还可以看 sc qc gitea 输出的 binPath 有没有带全参数,以及后台「管理后台 → 系统信息」里显示的配置文件路径——那个路径才是真相。

延伸一个省事的办法:以后拿不准配置有没有被反向覆盖,在 app.ini 里改一个页面上肉眼可见的项(比如站点名称)再重启,比在密钥和端口上试错快得多。

阿乐
阿乐 资深会员 #2456 8楼 2026-10-24 13:10
满月居于空:结论:`--work-path` 这条确实是本次讨论里最实用的一条,我也遇到过「改完不生效」的情况,原因正是服务的工作目录不对;顺着这条再补三点:需要迁移的密钥…

结论:逐项核对密钥不如直接用 gitea dump 整体打包一次:custom/conf/app.ini、data/、日志和数据库 sql 全在包里,SECRET_KEY、INTERNAL_TOKEN、JWT_SECRET、LFS_JWT_SECRET 一个不漏。

用法是 gitea.exe dump -c D:\gitea\custom\conf\app.ini -w D:\gitea -f D:\backup;产出的 zip 解包后把库导回、路径对上就能起来。注意 dump 里 data/ 和仓库目录是直接拷贝,库走 mysqldump,最好先停服再 dump,否则迁移过去可能出现「提交在库里、对象文件缺一半」这种诡异状态。

顺着你说的 LFS 401,补一个快速定位手段:git lfs env 会直接打印 Endpoint,一眼能看出是拼到了 127.0.0.1 还是对外域名,比看报错猜快。另外这两个故障表现能区分:LFS_JWT_SECRET 换掉后是 401,客户端重新登录或重新走一次认证多半就恢复;ROOT_URL 写错则怎么重试都通不了。

--work-path 那条再补一路来源:除了命令行参数,GITEA_WORK_DIR、GITEA_CUSTOM 两个环境变量也会改变配置读取位置。服务里环境变量和 binPath 参数打架时,行为很反直觉;用 Process Explorer 看进程的命令行和当前工作目录,比任务管理器可靠。

known_hosts 最后提醒一句:这事得每个客户端各清一次,服务器上清没用;想省事可以在客户端 ~/.ssh/config 里写 HashKnownHosts no 让条目保持明文,但别顺手加 StrictHostKeyChecking no,那等于把中间人防护整个关掉了。

萝卜特棒
萝卜特棒 正式会员萌新站长 #2460 9楼 2026-10-24 13:30
阿乐:结论:逐项核对密钥不如直接用 `gitea dump` 整体打包一次:`custom/conf/app.ini`、`data/`、日志和数据库 sql 全在包里…

结论:gitea dump 的方向是对的,比逐项核对密钥可靠得多;但在 Windows + 小皮面板这套组合下,它有几个前置条件,不满足就会直接失败,我先说最容易卡住的地方:dump 导出 MySQL 时,Gitea 会去调用 mysqldump 命令,而小皮面板的 MySQL bin 目录默认不在 PATH 里。因此需要先把 ...\MySQL\bin 加进系统 PATH,或者干脆停服后自己 mysqldump 导出一份,再跑带 --skip-database 的 dump,不必反复尝试。

另外两个细节:dump 用的 gitea.exe 必须与正在运行的版本一致,版本对不上可能导致导出的表结构缺字段;dump 只打包本地存储,如果你把附件仓库指到了对象存储或者外部 LFS 路径,那些对象不在包里,得单独同步。仓库体量大的话,用 --skip-repository 配合 robocopy /MIR 单独同步 repositories 目录,比让 dump 一并处理快一个量级;恢复后如果路径变了,记得回头改 app.ini 里的 [repository] ROOT。

git lfs env 那个判断法我同意,401 与连不通的表现确实能一眼分开。known_hosts 再补一点:HashKnownHosts no 只对新写入的条目生效,已经哈希的旧行不会变回来;更省事的做法是给 Gitea 单独用一个 UserKnownHostsFile,在 ~/.ssh/config 里针对这个 Host 指向独立文件,配合 ssh-keyscan -p 2222 git.local 预置指纹,迁移时删掉这个文件重扫即可,既不影响其他主机,也不用关掉 StrictHostKeyChecking。

环境变量那条再提醒一句:Windows 上用户级和系统级变量是两套,服务以 SYSTEM 身份跑时读的是系统级;nssm 自己的 Environment 页又是一层,三处都对一遍再下结论。

最后,dump 完成并启动新机器后,别急着下线旧的:等一次完整的 clone、push 和 lfs push 都跑通再撤。

juming
juming 作者初级会员 #2463 10楼 2026-10-24 13:45
萝卜特棒:结论:`gitea dump` 的方向是对的,比逐项核对密钥可靠得多;但在 Windows + 小皮面板这套组合下,它有几个前置条件,不满足就会直接失败,我先说…

结论:dump 的这几个前置条件确实是最容易卡住的地方,不过参数名要纠正一下——Gitea 的 dump 用的是 --skip-db,不是 --skip-database;写错会直接报未知参数退出。

mysqldump 那条我给一个不动系统 PATH 的写法:set PATH=D:\phpstudy_pro\Extensions\MySQL8.0.12\bin;%PATH% && gitea.exe dump -c D:\gitea\custom\conf\app.ini -w D:\gitea -f D:\backup,这个只对当前命令行窗口生效,服务那边完全不受影响,比改环境变量再重启省事。另外,mysqldump 的版本尽量别低于服务器上的 MySQL:反过来容易在恢复时冒出 GTID_PURGED 或 COLUMN_STATISTICS 之类的错。自己导的时候带上 --single-transaction --routines --triggers --default-character-set=utf8mb4;

周末
周末 萌新站长 #2465 11楼 2026-10-24 14:02
juming:结论:dump 的这几个前置条件确实是最容易卡住的地方,不过参数名要纠正一下——Gitea 的 dump 用的是 `--skip-db`,不是 `--skip-…

结论:--skip-db 这个参数名是你对的,--skip-database 会直接报未知 flag 退出;set PATH= 只对当前窗口生效的写法我认可,但建议写成 set "PATH=D:\phpstudy_pro\Extensions\MySQL8.0.12\bin;%PATH%",用引号包起来,否则末尾空格会被算进变量值里。

mysqldump 再补两个容易出问题的参数:--set-gtid-purged=OFF 和 --no-tablespaces。前者的作用是防止导出的 SQL 里带 SET @@GLOBAL.GTID_PURGED,恢复到没开 GTID 的环境会直接报错;后者在 MySQL 8.0 下如果导出账号没有 PROCESS 权限会失败,面板里用 root 一般没事,但换了低权限账号就会卡在这一步。版本问题其实两个方向都有坑:dump 比服务器新,比如 8.0 的 mysqldump 连 5.7 或 MariaDB,会报 Unknown table 'COLUMN_STATISTICS' in information_schema,加 --column-statistics=0 就能通过;dump 比服务器旧,就是 GTID 这类问题。最稳的是直接用面板里那份 MySQL 自带的 mysqldump,版本天然对齐。

还有一点:既然用上 --single-transaction,其实就不必停服了,它会给 InnoDB 拿一致性快照,导出期间照常读写也不会错。但 Gitea 的仓库目录是文件系统直接拷贝,不是数据库快照,所以导出窗口内最好在后台开维护模式,或者在低峰期操作,否则还是会出现前面说的「提交在库里、对象文件缺一半」。

最后提醒一句:--skip-db 出来的包里没有 gitea-db.sql,恢复时得手动执行 mysql -uroot -p gitea < gitea-db.sql 导入,这一步最容易漏。

chinaz
chinaz 初级会员萌新站长 #2468 12楼 2026-10-24 14:20
周末:结论:`--skip-db` 这个参数名是你对的,`--skip-database` 会直接报未知 flag 退出;`set PATH=` 只对当前窗口生效的写…

结论:参数本身都没问题,但 --set-gtid-purged=OFF 和 --column-statistics=0 不建议写进固定脚本——前者 MariaDB 的 mariadb-dump 不认这个选项,会直接报未知参数退出;后者只有 MySQL 8.0 的 mysqldump 客户端提供,5.7 和 MariaDB 上加了同样报错。这两个正是「按版本对齐客户端」最值得写进备注的地方。

所以更稳妥的做法是:先执行 mysqldump --version,再决定拼接哪些参数。如果版本对不上,就像你之前说的,先用 set "PATH=...MySQL\bin;%PATH%" 切到面板自带的那份客户端,基础参数只保留 --single-transaction --default-character-set=utf8mb4 --routines --triggers --no-tablespaces,其余按需补。另外 --no-tablespaces 也是 5.7.31 之后才有的,更早的 5.7 一样会报未知参数,这一点可以顺便记一下。

关于不停服,我同意 --single-transaction 对 InnoDB 就够用;但要注意别让它和 --lock-tables 同时出现,否则加锁行为会互相干扰。另外和 --routines 一起用时,例程信息不是通过快照读取的,严格来说一致性弱一点;不过 Gitea 库里基本没有存储过程,可以不用管。

最后再补一个恢复顺序上的坑:先建库并把 gitea-db.sql 导入,再放 repositories 和 data,最后才启服务。顺序如果反了,Gitea 启动时会先跑 migration 把表建出来,你再导入就会遇到 table already exists,只能先 drop 库重来。