在 CI/CD(如 GitHub Actions)高度普及的今天,选择“手动编译 + 强制推送”的博客部署方式似乎显得有些原始。但对于个人技术博客而言,这种方式让我能最大程度地掌控发布的每一个细节,同时也实现了“源码”与“静态产物”的物理隔离,避免了自动化脚本黑盒带来的调试焦虑。

本文不仅是简单的安装指南,更是从环境构建灾难恢复的全流程备忘录。文章重点解决了Hugo Extended 版本的环境依赖(针对 PaperMod 等需要 SCSS 编译的主题),详细拆解了基于 Git 的双仓库管理策略,并补充了在更换设备时如何通过子模块递归克隆实现“一键还原”的方案。

1. 核心环境与依赖

  • 操作系统:Windows 10/11 + WSL 2 (Ubuntu 24.04 LTS)
  • 生成器Hugo (Extended Version)
    • 关键点:由于我使用的 PaperMod 主题依赖 SCSS 编译和 PostCSS 功能,必须使用 Hugo Extended 版本,标准版会报错。
  • 版本控制:Git
  • 部署策略:本地编译 public 目录 -> git push -f 覆盖远端 GitHub Pages 仓库。

2. 环境搭建:安装 Hugo Extended

Ubuntu 默认 apt 源中的 Hugo 版本通常非常老旧且不包含 Extended 功能,因此强烈建议直接下载官方 .deb 包安装。

2.1 下载与安装

访问 Hugo GitHub Releases 页面获取最新版本链接(以下以 0.154.5 为例):

# 1. 下载 Extended 版本的 .deb 包 (请根据最新版本号修改 URL)
wget wget https://github.com/gohugoio/hugo/releases/download/v0.154.5/hugo_extended_0.154.5_linux-amd64.deb

# 2. 执行安装
sudo dpkg -i hugo_extended_0.154.5_linux-amd64.deb

2.2 验证安装

安装完成后,必须验证版本是否包含 extended 标识:

hugo version
# 预期输出示例: 
# hugo v0.125.0-5nd7s8d6+extended linux/amd64

注意:一定要看到 extended 字样才算成功。

3. 项目初始化与配置

3.1 创建站点

使用 Git Submodule 管理主题,保持项目结构整洁。

# 创建站点
hugo new site myblog
cd myblog

# 初始化 Git (源码库)
git init

# 拉取 PaperMod 主题
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod

3.2 关键配置 (hugo.toml)

编辑根目录下的 hugo.toml。这是构建时的唯一真理来源。

baseURL = "https://yourname.github.io/"  # ⚠️ 必须与 GitHub Pages 地址完全一致,且以 / 结尾,yourname 是 GitHub 用户名
languageCode = "zh-cn"
title = "Tech Memo"
theme = "PaperMod"

[params]
    defaultTheme = "auto"
    ShowCodeCopyButtons = true

4. 日常写作与发布流水线

这是每次更新文章时需要严格执行的标准操作序列。

第一步:新建文章

使用 Hugo CLI 生成带标准 Front Matter 的文件,避免手动创建出错。

hugo new content posts/my-new-post.md

使用编辑器打开并修改元数据:

  • draft: 将 true 改为 false(否则生成时会被跳过)。
  • date: 格式必须严格遵守 YYYY-MM-DD (如 2024-05-21)。

第二步:本地预览

启动本地服务器,实时查看渲染效果。

hugo server -D 
# -D 参数表示包含草稿 (Drafts),方便预览还未发布的文章

浏览器访问 http://localhost:1313 检查排版。

第三步:清理与编译 (Build)

确认无误后,停止预览,开始生成最终网页。为了防止历史残留文件导致的问题,建议先清理后构建

# 1. 彻底删除旧的构建目录
rm -rf public

# 2. 执行静态编译
hugo

执行成功后,根目录下会重新生成一个 public 文件夹,其中包含了网站所有的静态资源(HTML/CSS/JS)。

第四步:推送部署 (Deploy)

⚠️ 关键步骤:我们将 public 目录视为一个独立的、临时的 Git 仓库,每次都强制推送到 GitHub Pages。

# 1. 进入静态资源目录
cd public

# 2. 初始化为全新仓库 (抛弃旧的历史)
git init
git branch -M main

# 3. 关联远程仓库 (GitHub Pages 仓库)
git remote add origin https://github.com/yourname/yourname.github.io.git

# 4. 暂存并提交
git add .
git commit -m "Deploy: update blog content $(date '+%Y-%m-%d %H:%M')"

# 5. 强制推送到 GitHub
# 说明:因为是全新 init 的仓库,与远程历史不符,必须使用 -f (--force)
git push -u -f origin main

5. 核心原理:双仓库策略

为了保证数据安全和逻辑清晰,我采用了源码与产物分离的策略:

  1. 源码仓库 (Source)

    • 位置:本地 ~/myblog (推荐推送到 GitHub 私有仓库备份)。
    • 内容:Markdown 源码、配置文件、原始图片。
    • 设置:在 .gitignore 中添加 /public,防止编译产物污染源码库。
  2. 发布仓库 (Pages)

    • 位置:GitHub 上的 yourname.github.io
    • 内容:仅包含 public 文件夹内的 HTML/CSS/JS。
    • 逻辑:这是源码的“快照”。通过 rm -rf publicgit push -f,我们保证每次发布的都是最纯净的版本,且不需要在发布仓库保留冗余的 Commit 历史。

6. 避坑指南

  1. Extended 版本报错

    • 如果在执行 hugo 时出现 MIME typePostCSSTOCSS 相关的错误,99% 是因为你装成了 Hugo 标准版。请重新参照第 2 节安装 Extended 版。
  2. 样式丢失 (CSS 404)

    • 部署后如果页面只有文字没有排版,检查 hugo.toml 中的 baseURL
    • 它必须完全匹配你的 GitHub Pages URL(例如 https://username.github.io/),末尾的斜杠 / 最好加上。
  3. 文章不显示

    • 检查文章头部的 draft: true 是否改为了 false
    • 检查 date 是否是未来时间(Hugo 默认不渲染未来日期的文章)。
  4. 操作路径错误

    • hugo 构建命令必须在 项目根目录 执行。
    • git push 部署命令必须在 public 目录 内执行。

7.备份与还原流程

基于“源码”与“产物”分离的双仓库策略,我们的备份重心完全在于源码仓库 (Source Repo)。只要源码在,网站随时可以重生。以下是日常备份和更换电脑时的还原步骤。

1.源码日常备份

在写完文章并部署(git push -f 到了 GitHub Pages)之后,不要忘记将源码同步到你的私有仓库。

操作位置:项目根目录 ~/myblog

# 1. 确认不在 public 目录中
cd ~/myblog

# 2. 提交源码变更
git add .
git commit -m "Backup: add new post and update config"

# 3. 推送到私有源码仓库 (Source Repo)
git push origin main

注意:由于 .gitignore 中已经忽略了 /public 目录,这里只会上传 Markdown、配置文件和主题设置,不会上传生成的 HTML 垃圾。

2.异地还原/迁移 (更换电脑/重装系统)

假设你在一台全新的 WSL 环境中,需要恢复写作环境,请严格按照以下步骤操作。

第一步:安装环境 重新按照本文第 2 节的方法,安装 Hugo Extended 版本。

第二步:克隆源码 (一步到位) 使用 --recursive 参数,在克隆源码仓库的同时,自动拉取 PaperMod 主题文件(子模块)。

# 核心命令:--recursive 会自动处理子模块
git clone --recursive https://github.com/yourname/myblog-source.git myblog

cd myblog

第三步:验证与恢复 此时,源码和主题都已就绪。你可以直接尝试运行本地预览:

hugo server -D

如果一切正常,即可开始新一轮的写作。下次发布时,Hugo 会自动重新创建 public 目录,你无需手动从旧电脑拷贝该文件夹。

3.常见问题处理

  • 忘记加 –recursive 怎么办? 如果你手快直接用了 git clone,你会发现 themes/PaperMod 文件夹是空的,Hugo 会报错。此时在项目根目录补救执行以下命令即可:
    git submodule update --init --recursive
    
  • Public 目录冲突:如果在还原后发现 public 目录里有奇怪的文件,直接 rm -rf public 删掉即可,Hugo 会负责重新生成。