基于 Hugo + Git LFS + GitHub Actions 搭建稳定大容量博客架构

基于 Hugo + Git LFS + GitHub Actions 搭建稳定大容量博客架构

一、底层模板:Hugo Theme Stack 启动模板说明

当前整套博客基于官方脚手架仓库 hugo-theme-stack-starter 二次开发,该模板是 Stack 主题官方推荐快速启动模板,也是本架构的底层基础。本文所有改造、配置与自动化流程,均依托此模板实现。

1.1 模板仓库与核心特性

官方仓库地址:https://github.com/CaiJimmy/hugo-theme-stack-starter

模板原生能力:

  • 采用 Hugo Modules 加载主题,无需手动拷贝主题文件,版本管理规范
  • 预置完整站点目录与默认配置,开箱即用
  • 内置 GitHub Actions 工作流,自动构建并部署至 GitHub Pages
  • 配置定时任务,每日自动检测、更新主题版本
  • 同时支持本地运行、GitHub Codespaces 在线运行两种环境

1.2 前置运行依赖

本地部署模板需提前安装依赖(GitHub Codespaces 已预装,可跳过):

1
2
3
Git
Go
Hugo Extended 扩展版本

参考官方安装文档:https://gohugo.io/installation/

1.3 模板标准搭建流程

1.3.1 基于模板创建仓库
  1. 进入模板仓库主页,点击 Use this template 新建仓库
  2. 仓库命名规范

    • 个人博客主站:命名为 `<用户名>.github.io`,访问地址:`https://<用户名>.github.io`
    • 自定义仓库名:访问地址:`https://<用户名>.github.io/仓库名/`
1.3.2 配置 GitHub Pages 部署源
  1. 进入仓库 → Settings → Pages
  2. 找到 Build and deployment 模块,将 Source 设置为 GitHub Actions
1.3.3 站点本地预览
方式一:GitHub Codespaces 在线预览
  1. 仓库页面点击 =Create codespace=,等待环境初始化
  2. 终端执行预览命令:
1
hugo server
方式二:本地克隆运行
1
2
3
git clone 你的公开仓库地址
cd 仓库目录
hugo server
1.3.4 站点基础配置

所有配置文件统一存放于 config/_default/ 目录,核心配置项: 编辑 config/_default/config.toml=,修改 =baseurl 为博客实际域名。

示例配置:

1
2
3
4
5
;; 仓库名为 用户名.github.io
baseurl = "https://xxx.github.io/"

;; 自定义仓库名称
baseurl = "https://xxx.github.io/仓库名/"
1.3.4.1 配置文件格式说明

本主题及官方模板默认采用 TOML 作为配置文件格式,而非 YAML。 全站 `config/` 目录下所有配置均使用 TOML 语法编写,请勿混用格式,避免编译报错。

1.3.4.2 Giscus 评论配置(私有仓库隔离方案)

出于安全考虑,Giscus 评论相关配置文件不存放在公开站点仓库,统一放置在**私有内容仓库**中。 部署流程中通过 GitHub Actions 脚本动态读取并合并配置,实现敏感信息隔离。

  1. 私有仓库目录结构

giscus.toml 放置在私有仓库 content/post/ 目录下,与博文同级。

  1. Actions 动态合并逻辑

构建阶段先清空原有评论配置,再将私有仓库内的 giscus.toml 追加至站点主配置文件:

1
2
3
4
sed -i '/^\[comments\]/,/^$/d' config/_default/params.toml
if [ -f "content/post/giscus.toml" ]; then
  cat content/post/giscus.toml >> config/_default/params.toml
fi

优势:

  • 评论密钥、仓库地址等敏感配置仅留存私有仓库,降低泄露风险
  • 公开仓库保持纯净,仅保留站点通用配置
  • 依托现有双仓库架构,无需额外改造目录与权限
  1. giscus.toml 内容格式
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[comments]
  enabled = true
  provider = "giscus"
  [comments.giscus]
      repo = "ynhugo/ynhugo.github.io"
      repoID = "R_xxxxxxxxxx"
      category = "Announcements"
      categoryID = "DIC_xxxxxxxxxxxxxxx"
      mapping = "pathname"
      lightTheme = "light"
      darkTheme = "dark"
      reactionsEnabled = 1
      emitMetadata = 0
1.3.5 提交与自动发布

修改完成后执行常规 Git 推送,GitHub Actions 自动完成构建与部署:

1
2
3
git add .
git commit -m "更新站点内容/配置"
git push
1.3.6 一键自动化配置(分步执行版)

https://github.com/CaiJimmy/hugo-theme-stack-starter

https://github.com/ynhugo/ynhugo.github.io

git clone git@github.com:ynhugo/ynhugo.github.io.git ynhugo cd ynhugo

hugo mod get -u github.com/CaiJimmy/hugo-theme-stack/v4 hugo mod tidy

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
# 修改baseurl
sed -i 's|\(^baseurl = "\).*\("\)|\1https://ynhugo.github.io/\2|g' config/_default/config.toml
# 修改语言
sed -i 's|\(^locale[[:space:]]*= "\).*\("\)|\1zh-cn\2|g' config/_default/config.toml
# 修改title
sed -i 's|\(^title[[:space:]]*= "\).*\("\)|\1ynhugo\2|g' config/_default/config.toml
# 修改默认博文语言
sed -i 's|\(^defaultContentLanguage[[:space:]]*= "\).*\("\)|\1zh-cn\2|g' config/_default/config.toml
# 修改每页显示博文数量
sed -i 's|\(^[[:space:]]*pagerSize[[:space:]]*= \).*|\120|g' config/_default/config.toml

# 4. 创建中文页面(纯本地操作,批量复制执行)
# 添加中文归档
cat > content/page/archives/index.zh-cn.md << 'EOF'
---
title: "文章归档"
date: 2019-05-28
layout: "archives"
slug: "archives"
menu:
    main:
        weight: -70
        params:
            icon: archives
---
EOF

# 添加中文主页
cat > content/_index.zh-cn.md << 'EOF'
---
menu:
    main:
        name: "主页"
        weight: 1
        params:
            icon: home
---
EOF

# 添加中文搜索
cat > content/page/search/index.zh-cn.md << 'EOF'
---
title: "搜索"
slug: "search"
layout: "search"
outputs:
    - html
    - json
menu:
    main:
        weight: -60
        params:
            icon: search
---
EOF

# 添加中文友情链接
cat > content/page/links/index.zh-cn.md << 'EOF'
---
title: 友情链接
links:
  - title: GitHub
    description: GitHub is the world's largest software development platform.
    website: https://github.com
    image: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
menu:
    main:
        weight: 4
        params:
            icon: link
comments: false
---
EOF

# 5. 生成短代码脚本(本地操作,批量复制执行)
#+BEGIN_SRC bash
cat - > shortcode.sh << 'END'
mkdir -p layouts/shortcodes/
# 添加网易云短代码
cat - > layouts/shortcodes/netease.html <<'EOF'
<iframe
  frameborder="no"
  border="0"
  marginwidth="0"
  marginheight="0"
  width=330 height=86
  src="//music.163.com/outchain/player?type=2&id={{.Get 0}}&auto=0&height=66">
</iframe>
EOF
# 添加文字属性
cat - > layouts/shortcodes/align.html <<'EOF'
<p style="text-align:{{ index .Params 0 }}">{{ index .Params 1 | markdownify }}</p>
EOF
# 插入github仓库
cat - > layouts/shortcodes/github.html <<'EOF'
<div class="github">
    <div class="logo">
        {{ replace $.Site.Data.SVG.repository "icon" "icon github-icon" | safeHTML }}
        <a class="name" href={{ .Get "link" }} target="_blank">{{ .Get "name" }}</a>
    </div>
    <div class="description">{{ .Get "description" }}</div>
    <div class="language">
        <span class="language-color" style="background-color: {{ .Get "color" }}"></span>
        <span class="language-name">{{ .Get "language" }}</span>
    </div>
</div>
EOF
END
chmod +x shortcode.sh

# 6. 注入 Actions 流程(本地操作,批量复制执行)
sed -i 's|\(^[[:space:]]*\)\(hugo \\\)|\1echo "添加短代码"\n\1./shortcode.sh\n\1\2|g' .github/workflows/deploy.yml

git add . git commit -m "初始化博客配置" git push

1.4 Stack 主题版本管理

模板默认使用 Stack 主题 v4 版本,通过 Hugo Modules 统一管理依赖。

1.4.1 手动更新主题

站点根目录执行命令,拉取最新主题并整理依赖:

1
2
hugo mod get -u github.com/CaiJimmy/hugo-theme-stack/v4
hugo mod tidy
1.4.2 版本说明

受 Go Modules 机制限制,若后续主题发布 v4 以上大版本,需要手动修改 config/module.toml 内的主题版本路径。

1.5 与现有架构兼容说明

  1. 目录与配置:公开仓库完全沿用模板原生目录结构、配置体系、Hugo Modules 规则,无需改动。
  2. 自动化任务:现有 update-theme.yml 主题定时更新工作流,与模板原生能力一致,可长期保留使用。
  3. 部署流程:自定义的 deploy.yml 融合了模板部署逻辑 + Hugo 编译缓存 + 私有仓库拉取 + Git LFS 资源加载,完全向下兼容。
  4. 写作规范:Stack 主题强制要求文章头部使用 YAML 数组格式标签,禁止纯空格分隔标签,避免渲染报错。

1.6 多平台部署参考

如需部署到 GitHub Pages 以外的静态托管平台,可参考 Hugo 官方文档: https://gohugo.io/host-and-deploy/

二、整体架构介绍

2.1 目录结构

采用「博文+配套资源同目录」结构,不拆分文件、不使用外部图床,贴合日常写作习惯,无需适配特殊路径。

1
2
3
4
5
6
7
8
blogs/
├── post/                ;; 所有博文目录
│   ├── 分类目录/
│   │   ├── 文章.org/.md
│   │   └── resources/   ;; 图片、PDF、压缩包、源码包等资源文件
├── auto-lfs-tracker.sh  ;; LFS 自动管理脚本
├── .gitattributes       ;; Git LFS 规则配置文件
└── .git/hooks/pre-push  ;; Git 前置钩子,自动触发扫描脚本

2.2 技术选型与设计思路

  • 核心载体:Git + GitHub 仓库统一存储博文与配套资源
  • 静态站点:使用 Hugo 作为静态博客生成器
  • 大文件方案:基于 Git LFS 托管图片、压缩包、PDF 等大容量资源,彻底避免 .git 目录无限膨胀
  • 自动化能力:Shell 脚本 + Git Hook 联动,推送代码前自动识别新资源文件类型,自动纳入 LFS 托管;搭配 GitHub Actions 实现全自动编译、发布
  • 部署方案:GitHub Actions 自动拉取私有仓库代码与 LFS 资源,借助 Hugo 编译后发布静态博客站点
方案优势
  1. 资源与博文同目录绑定,路径无需手动修改,完全贴合原生写作习惯
  2. 大文件统一 LFS 托管,仓库体积可控,长期更新不臃肿
  3. 全流程自动化配置,一次部署终身零维护
  4. 兼容私有仓库、公开部署、CI 编译、多设备克隆等全部场景

2.3 双仓库整体架构说明

采用**私有内容库 + 公开站点库**分离架构,兼顾原始数据安全与博客公开访问需求:

  • 私有仓库:`blogs`,存储原始博文、资源文件、自动化脚本、配置文件,对外完全不可见,保障源码与资源安全
  • 公开仓库:`ynhugo.github.io`,仅存储 Hugo 编译完成的静态网页文件,作为 GitHub Pages 对外访问入口

2.4 权限体系:细粒度 Token + 同名 Secrets

整套架构依靠**单个细粒度 Personal Access Token** 实现双仓库跨仓权限互通,两个仓库统一使用同名 Secrets 存储密钥,配置极简、维护便捷。

2.4.1 创建细粒度访问令牌

令牌创建地址:https://github.com/settings/personal-access-tokens

  1. 点击 Generate new token,选择 Fine-grained token(细粒度令牌)
  2. 自定义令牌名称、有效期、用途备注,按需配置长期有效
  3. 仓库范围:精准勾选两个业务仓库

    • `ynhugo/blogs`(私有内容仓库)
    • `ynhugo/ynhugo.github.io`(公开部署仓库)
  4. 仓库最小权限配置

    • Metadata:Read(读取仓库基础信息,系统必选)
    • Code:Read and Write(支持代码拉取、推送、LFS 资源读写)
  5. 生成令牌后**立即复制备份**,页面刷新后无法再次查看密钥。
2.4.2 仓库配置同名 Secrets

将同一 Token 密钥,分别配置到两个仓库的 Actions 密钥中,**密钥名称完全一致**:

  • 私有仓库 blogs:Settings → Secrets and variables → Actions 新建密钥

    • 名称:`PRIVATE_BLOG_REPO_TOKEN`
    • 值:粘贴统一 Token
  • 公开仓库 ynhugo.github.io:同路径新建同名密钥

    • 名称:`PRIVATE_BLOG_REPO_TOKEN`
    • 值:粘贴**完全相同的 Token**
2.4.3 配置优势
  1. 单 Token 管控双仓库,密钥轮换、更新仅需操作一次,大幅降低维护成本
  2. 同名 Secrets 统一配置,GitHub Actions 调用语法一致,无需区分环境
  3. 细粒度权限精准限制仓库与操作范围,安全性远高于传统全局 Token
  4. 完美覆盖私有仓库推送、公开仓库跨仓克隆、LFS 资源拉取、静态文件推送等全部场景

2.5 全链路流转流程

完整链路:**本地编辑 → 钩子自动化检测 → 同步私有仓库 → Actions 拉取编译 → 发布至 gh-pages 分支 → 公网访问**

  1. 本地编辑阶段

    • 在本地 `blogs` 仓库新增、修改 `.md/.org` 博文,同步更新 `resources` 目录下的图片、PDF、压缩包等资源,保持原生目录结构。
  2. 本地提交与钩子触发

    • 执行常规 Git 提交推送命令:
1
2
3
git add .
git commit -m "更新博文/补充资源"
git push
  • 执行 `git push` 瞬间优先触发 `pre-push` 前置钩子
  • 自动调用 `auto-lfs-tracker.sh –scan-only` 脚本
  • 仅扫描新文件类型、更新 LFS 规则配置,**不执行任何提交操作**,不打断推送流程
  • 自动补全缺失的 LFS 追踪规则,确保新增资源全部纳入 LFS 托管
  1. 同步至私有 GitHub 仓库

    • 文本类文件(博文、脚本、配置)通过标准 Git 机制推送
    • 大体积资源文件,同步 LFS 指针文件与实体文件至 GitHub LFS 服务
    • 私有仓库完整留存原始博文、配置、LFS 资源,实现数据安全隔离
  2. 公开仓库 Actions 自动拉取

    • 公开仓库工作流自动触发,通过配置密钥鉴权执行操作:

      • 读取 `PRIVATE_BLOG_REPO_TOKEN` 密钥,鉴权克隆私有 `blogs` 仓库
      • 开启 LFS 自动下载,根据指针文件拉取完整实体资源,彻底规避页面资源 404 问题

*补充说明*:GitHub Actions 内置缓存**无法缓存 Git LFS 实体文件**,每次构建都会重新完整下载 LFS 资源,该现象为当前方案固有特性。

1
2
3
4
5
6
7
8
steps:
  - name: Clone private blogs repo
    uses: actions/checkout@v4
    with:
      repository: ynhugo/blogs
      token: ${{ secrets.PRIVATE_BLOG_REPO_TOKEN }}
      path: content/post
      lfs: true  # 开启 LFS 自动下载
  1. 编译与发布站点

    • 调用 Hugo 编译工具,基于原始博文与完整资源生成纯静态网页
    • 将编译完成的 public 静态资源,强制推送至公开仓库 `gh-pages` 分支
    • GitHub Pages 自动监听 `gh-pages` 分支,对外提供公网访问
  2. 最终访问链路

本地文件 → 私有仓库(Git代码+LFS资源)→ GitHub Actions + Hugo 编译 → 公开仓库 gh-pages 分支 → 终端用户访问

2.5.1 公开仓库 Actions 核心工作流
  1. 拉取私有仓库:通过统一密钥鉴权克隆私有内容仓库,自动下载全部 LFS 资源
  2. Hugo 编译:读取原始博文与资源,编译生成完整静态网站
  3. 分支部署:将静态文件推送至公开仓库 `gh-pages` 分支
  4. 站点上线:GitHub Pages 加载分支资源,自动更新公开博客站点

最终效果

  • 原始文章、私有资源仅存于私有仓库,安全不泄露
  • 静态页面统一托管公开仓库分支,公网正常访问
  • 全程自动化,无需人工干预,无部署冲突
2.5.2 Pre-Push 钩子时序与 .gitattributes 推送机制
执行时序(Git 官方固定规则)

`git push` 执行顺序:**优先运行 pre-push 钩子 → 钩子执行完毕 → 执行真正的远程推送** 所有 LFS 扫描、规则更新动作均在推送前完成,无规则遗漏、无执行时序错乱问题。

配置文件推送逻辑

脚本采用 `–scan-only` 纯扫描模式,核心特性:**仅本地修改 .gitattributes,不自动提交**

  1. 本次 `git push`:仅推送**上一次已提交**的代码和资源,不推送本次更新的 `.gitattributes`
  2. 更新后的 `.gitattributes` 保留为**本地未提交修改**
  3. 在下一次手动 `git add && git commit` 时统一提交
  4. 随下一次 `git push` 推送至远程私有仓库
机制优势
  • 不破坏原生 Git 推送流程,无冲突、无推送中断风险
  • 自动迭代 LFS 规则,无需手动维护配置
  • 规则滞后一次提交为安全兜底,不影响当前资源托管与站点部署

2.6 GitHub Actions 工作流(完整配置)

本架构采用「私有仓库触发 → 公开仓库构建」的自动化部署模式,共包含 3 个工作流文件:

  • 私有仓库:1 个触发部署工作流
  • 公开仓库:1 个构建部署工作流 + 1 个主题自动更新工作流
2.6.1 私有仓库工作流(触发部署)

路径:.github/workflows/trigger-deploy.yml 作用:私有仓库内容更新后,自动通知公开仓库重新构建博客

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
name: Trigger public repo deploy
on:
  push:
    branches:
      - main
      - master

jobs:
  trigger:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger public site rebuild
        uses: peter-evans/repository-dispatch@v3
        with:
          token: ${{ secrets.PRIVATE_BLOG_REPO_TOKEN }}  # 这行必须加!
          repository: ynhugo/ynhugo.github.io
          event-type: blog-updated
2.6.2 公开仓库工作流(构建与部署)

路径:.github/workflows/deploy.yml 作用:浅克隆私有博客内容 → 启用 Hugo 编译缓存加速构建 → 编译站点 → 发布到 gh-pages

补充说明

  1. 配置 `–cacheDir` 指向 Actions 临时目录,仅缓存 Hugo 编译产物、页面渲染资源,可显著缩短编译阶段耗时;
  2. 本缓存对 Git LFS 大文件不生效,LFS 资源每次都会重新拉取,也是整体部署耗时的主要来源;
  3. 开启 `–depth 1` 浅克隆,最大程度压缩纯 Git 文本文件的拉取耗时。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
name: Build and deploy

on:
  push:
    branches: [ main, master ]
  workflow_dispatch:
  repository_dispatch:
    types: [blog-updated]

env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

permissions:
  contents: write

concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout main
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      # 缓存 Hugo 构建目录(官方标准写法,绝对不报错)
      - name: Setup Hugo cache
        uses: actions/cache@v4
        with:
          path: ${{ runner.temp }}/hugo_cache
          key: ${{ runner.os }}-hugo-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-hugo-

      # 浅克隆私有仓库(你原来的配置)
      - name: Clone private posts (shallow)
        run: |
          git clone --depth 1 --branch main \
          https://${{ secrets.PRIVATE_BLOG_REPO_TOKEN }}@github.com/ynhugo/blogs.git content/post

      - name: List posts
        run: ls -la content/post

      - name: Clean old public
        run: rm -rf public

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: 'latest'
          extended: true

      - name: Apply giscus config
        run: |
          sed -i '/^\[comments\]/,/^$/d' config/_default/params.toml
          if [ -f "content/post/giscus.toml" ]; then
            cat content/post/giscus.toml >> config/_default/params.toml
          fi

      # 正确官方写法:--cacheDir 不会报错
      - name: Build site
        run: |
          ./shortcode.sh
          hugo --minify --gc --logLevel error --cacheDir "${{ runner.temp }}/hugo_cache"

      - name: Deploy to gh-pages
        uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public
          publish_branch: gh-pages
          keep_files: true
2.6.3 公开仓库工作流(主题自动更新)

路径:.github/workflows/update-theme.yml 作用:每日自动更新 Hugo 主题,无需手动维护

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
name: Update theme

# Controls when the workflow will run
on:
  schedule:
    # Update theme automatically everyday at 00:00 UTC
    - cron: "0 0 * * *"
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  update-theme:
    runs-on: ubuntu-latest

    permissions:
      # Give the default GITHUB_TOKEN write permission to commit and push the
      # added or changed files to the repository.
      contents: write
    
    steps:
      - uses: actions/checkout@v6

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: 'latest'
          extended: true

      - name: Update theme
        run: hugo mod get -u

      - name: Tidy go.mod, go.sum
        run: hugo mod tidy

      - name: Commit changes
        uses: stefanzweifel/git-auto-commit-action@v7
        with:
          commit_message: "CI: Update theme"

2.7 架构亮点总结

  • 单 Token 管控双仓库,同名 Secrets 统一配置,极简易维护
  • 细粒度最小权限设计,兼顾安全与实用性
  • 基于 Hugo 构建静态博客,搭配 Git LFS 管理大体积资源
  • 源码资源私有隔离,静态页面公开部署,权限边界清晰
  • 钩子+脚本全自动化,一次配置长期零维护
  • 执行时序安全可控,规则更新稳定无风险

2.8 部署耗时说明

结合实测结果,对当前架构部署耗时做客观说明:

Git LFS + 双仓库 架构下,部署耗时主要分为两部分:

  1. *LFS 资源拉取*:GitHub Actions 无法缓存 Git LFS 实体文件,每次构建都需要完整下载图片、PDF 等大体积资源,这是整体部署耗时(4~5 分钟)的核心来源,属于该方案固有限制。
  2. *Hugo 编译*:通过 `–cacheDir` 开启编译缓存后,仅首次编译耗时较长,后续增量编译可压缩至秒级。

优化选择:

  • 沿用现有架构:目录统一、写作习惯无改动、数据全托管在 GitHub,稳定性与易用性更强,接受 4~5 分钟部署耗时即可。
  • 极致提速方案:将大体积资源迁移至外部图床/对象存储,博文使用在线链接引用,彻底脱离 Git LFS,部署耗时可降至 30 秒内。

三、前置环境准备

3.1 安装 Git 与 Git LFS

主流 Linux / macOS 环境执行安装命令:

1
2
3
# 安装 Git(多数系统默认预装)
# 安装 Git LFS
git lfs install

验证安装:

1
git lfs version

3.2 初始化博客仓库

全新仓库可执行初始化,已有仓库可跳过:

1
2
3
4
cd ~/blogs/blogs
git init
git config user.name "你的用户名"
git config user.email "你的邮箱"

四、核心配置:Git LFS 自动化方案

4.1 智能扫描脚本(auto-lfs-tracker.sh)

仓库根目录创建自动化脚本,支持多运行模式、自动扫描规则、内置全套排错命令:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/bin/bash
set -e

SCAN_DIR="post"
CONFIG_FILE=".gitattributes"
SCAN_ONLY=false

if [[ "$1" == "--help" || "$1" == "-h" ]]; then
cat <<EOF
=============================================
        智能 Git LFS 自动追踪工具(加固终极版)
=============================================
【使用】
   ./auto-lfs-tracker.sh          # 自动扫描 + 提交配置
   ./auto-lfs-tracker.sh --scan-only # 仅扫描(钩子专用,不提交)
   ./auto-lfs-tracker.sh --help   # 查看帮助

=============================================
【一、历史大文件迁移到 LFS(仅执行一次)】
  作用:将仓库旧大文件转为 LFS 托管
=============================================
git lfs migrate import --everything --include="**/resources/**/*"
git push origin main --force

=============================================
【二、迁移后 .git 瘦身清理(必做)】
  作用:删除旧历史,从 GB → MB 级别
=============================================
git reflog expire --all --expire=now
git gc --prune=now --aggressive

=============================================
【三、pre-push 钩子安装(push 自动检查)】
  作用:每次 push 前自动扫描新文件类型
=============================================
cat > .git/hooks/pre-push << 'EOF_HOOK'
#!/bin/bash
echo "🔍 Git Push 前自动检查 LFS 未追踪文件(仅扫描)..."
./auto-lfs-tracker.sh --scan-only
EOF_HOOK
chmod +x .git/hooks/pre-push
chmod +x auto-lfs-tracker.sh

=============================================
【四、🔥 GitHub Actions / 克隆 404 / GH008 错误修复】
【报错:Object does not exist on the server / unknown Git LFS object】
  作用:把本地 LFS 大文件真正上传到 GitHub 服务器(必执行)
=============================================
git lfs push origin main --all
git push origin main --force

=============================================
【五、.sh 脚本误进 LFS 修复】
【报错:Smudge error 下载 sh 文件失败】
  作用:把脚本移出 LFS,恢复正常文本文件
=============================================
git lfs untrack "*.sh"
git add --renormalize auto-lfs-tracker.sh
git add .gitattributes
git commit -m "fix: 移除 .sh 从 LFS"
git push origin main --force

=============================================
【脚本作用】
1. 自动扫描 post/ 目录所有资源文件
2. 自动追加未追踪的类型到 Git LFS
3. 自动保护 **/resources/**/* 全部托管
4. 自动排除 .sh/.md/.org 等文本文件
5. 自动排除编辑器临时文件 *Minibuf* .DS_Store
6. 防止 Git 仓库爆炸、保证 CI 正常运行
7. 加固防 GH008 推送拒绝错误
=============================================
EOF
exit 0
fi

if [[ "$1" == "--scan-only" ]]; then
  SCAN_ONLY=true
  echo "============================================="
  echo "       智能 Git LFS 扫描模式(仅检查)"
  echo "============================================="
fi

cd "$(dirname "$0")"

echo -e "\n📂 扫描目录:$SCAN_DIR"

# 🔥 加固:排除文本、脚本、配置、编辑器临时文件
all_exts=$(find "$SCAN_DIR" -type f | \
  grep -vE '\.md$|\.org$|\.sh$|\.git|\.gitattributes|\.gitignore|README|LICENSE|^\./|/\.|Minibuf|\.DS_Store' | \
  sed -e 's/^.*\.//' | sort -u | grep -v '^/' | grep -v '^$' | grep -v ' ' | head -30)

echo -e "\n🔍 扫描到的文件类型:"
echo "$all_exts"

existing_patterns=$(git lfs track | awk '{print $1}')
added=0

for ext in $all_exts; do
    # 🔥 加固:过滤非法后缀、空后缀、带空格的垃圾文件
    if [[ -z "$ext" || "$ext" =~ " " || "$ext" =~ "/" || "$ext" =~ "*" ]]; then
        continue
    fi

    pattern="*.${ext}"
    if ! echo "$existing_patterns" | grep -qx "$pattern"; then
        echo "✅ 新增 LFS 追踪:$pattern"
        git lfs track "$pattern"
        added=$((added + 1))
    fi
done

# 强制全局 resources 规则
if ! grep -q "**/resources/**/\*" "$CONFIG_FILE"; then
    echo "✅ 启用全局规则:**/resources/**/*"
    git lfs track "**/resources/**/*"
    added=$((added + 1))
fi

# 钩子模式:不提交
if [[ "$SCAN_ONLY" == true ]]; then
  echo -e "\n✅ 扫描完成(钩子模式:不提交)"
  exit 0
fi

if [ $added -gt 0 ]; then
    echo -e "\n📝 提交配置..."
    git add "$CONFIG_FILE"
    git commit -m "auto: lfs 自动追踪新文件类型"
    echo -e "\n🎉 更新完成!"
else
    echo -e "\n🎉 所有类型已追踪,无需更新!"
fi

echo -e "\n✅ 全部完成!"

添加脚本执行权限:

1
chmod +x auto-lfs-tracker.sh

4.2 配置 Git Pre-Push 钩子

实现每次 `git push` 前自动扫描 LFS 规则,全程无感自动化:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/bin/bash
set -e

echo "=================================================="
echo " 🔒 安全加固版 Git LFS 预检查(仅扫描,零风险)"
echo " 作用:自动检查新文件类型 → 自动维护 LFS 规则"
echo " 承诺:不提交、不推送、不修改、不冲突、不中断"
echo "=================================================="

./auto-lfs-tracker.sh --scan-only

echo -e "\n✅ LFS 预检查完成,继续正常推送..."
exit 0
1
chmod +x .git/hooks/pre-push

4.3 存量历史文件迁移(仅执行一次)

针对已有大量资源的旧仓库,批量将历史大文件迁移至 LFS,实现仓库瘦身:

  1. 迁移历史资源文件
1
git lfs migrate import --everything --include="**/resources/**/*"
  1. 清理 Git 历史垃圾对象
1
2
git reflog expire --all --expire=now
git gc --prune=now --aggressive
  1. 强制推送重写历史(单人私有仓库安全)
1
git push origin main --force

4.4 上传 LFS 实体文件(解决 404 报错)

migrate 仅修改提交记录,需手动推送实体文件至远程,避免 CI/克隆资源404:

1
2
git lfs push origin main --all
git push origin main --force

五、日常使用流程

5.1 常规写作与提交

完全保留原生 Git 操作习惯,无需额外干预:

1
2
3
git add .
git commit -m "更新博文:xxx"
git push

推送时钩子自动触发 LFS 扫描,补全缺失规则,全程自动化。

5.2 手动执行扫描脚本

灵活手动维护 LFS 规则:

1
2
3
4
5
6
7
8
# 完整扫描并提交新规则
./auto-lfs-tracker.sh

# 仅扫描不提交(钩子同款模式)
./auto-lfs-tracker.sh --scan-only

# 查看帮助与全套排错命令
./auto-lfs-tracker.sh -h

六、常见问题排错

6.1 克隆/CI 报错:Object does not exist on the server (404)

原因:本地 LFS 实体文件未推送至远程服务器 解决:

1
2
git lfs push origin main --all
git push origin main --force

6.2 Shell 脚本被纳入 LFS,克隆失败

原因:.sh 脚本被误追踪,文本文件无需 LFS 托管 解决:

1
2
3
4
5
git lfs untrack "*.sh"
git add --renormalize auto-lfs-tracker.sh
git add .gitattributes
git commit -m "fix: 移除 .sh 文件从 LFS 托管"
git push origin main --force

6.3 git push 被钩子中断、出现提交冲突

原因:钩子模式下脚本执行了 git commit,打乱推送流程 解决方案:使用 –scan-only 仅扫描不提交(本文钩子已默认配置)

6.4 .git 目录体积偏大

原因:migrate 操作后 Git 保留了旧历史对象,需手动垃圾回收 解决方案:

1
2
git reflog expire --all --expire=now
git gc --prune=now --aggressive

6.5 Actions 克隆私有仓库权限不足

原因:Token 权限缺失、Secrets 名称错误、未勾选对应仓库 排查要点:

  1. 核对细粒度 Token 已勾选 blogs 和 ynhugo.github.io 两个仓库
  2. 确认 Token 拥有 Metadata(Read)、Code(Read and Write) 权限
  3. 检查 Actions 配置中密钥名称为 PRIVATE_BLOG_REPO_TOKEN(区分大小写)
  4. 重新粘贴 Token 至仓库 Secrets,确保无多余空格

6.6 GitHub Actions 部署总耗时 4~5 分钟,速度偏慢

原因:GitHub Actions 无法缓存 Git LFS 大文件,每次构建都会完整拉取所有 LFS 资源,仓库资源体量越大,耗时越长。

解决方案:

  1. 现有架构无需处理:该速度为 Git LFS 方案下的正常极限速度,不影响功能使用,可直接忽略;
  2. 极致提速方案:将图片、压缩包、PDF 等大资源迁出 Git 仓库,托管至外部图床/对象存储,博文使用在线链接引用,彻底规避 LFS 重复下载问题。

七、方案总结

  1. 目录结构兼容传统写作习惯,博文与资源同目录,无需修改文件路径;
  2. Git LFS 专门托管大体积资源,从根源解决 Git 仓库无限膨胀问题;
  3. 脚本 + Git Hook 实现全自动化,新增文件自动识别并纳入 LFS;
  4. 细粒度 Token + 同名 Secrets 实现双仓库权限互通,安全且易维护;
  5. 脚本内置全套排错命令,换设备、重装环境均可快速复原;
  6. 基于 Hugo + Stack 主题模板搭建静态博客,采用 TOML 格式配置,完美适配 GitHub Actions 自动部署,私有内容隔离,公开站点正常访问;
  7. Giscus 评论配置独立存放在私有仓库,通过 Actions 动态合并,兼顾功能与数据安全;
  8. 钩子时序逻辑安全可控,配置文件更新无冲突、无推送风险,长期稳定运行。

*注*:本方案基于 Git LFS 实现大文件托管,受 GitHub 机制限制,CI 部署会存在固定资源拉取耗时,属于正常现象。

本方案适合大容量个人博客、技术文档库,一次完整配置后,可实现长期零维护稳定运行。