🚀 小白搭建个人博客教程(二)—— 自动化部署
上一篇教程里,我们从零开始搭建好了一个博客,也成功把它发布到了网上。但每次写完文章,都要手动敲一串命令去部署,说实话……还是有点烦的😅
1 | hexo clean && hexo generate && hexo deploy |
那有没有一种方式,写完文章往 GitHub 上一推,博客就自动更新了呢?
答案是:有的!用 GitHub Actions 就能实现全自动部署。今天我们就来把这套流程配好,以后写博客就只需要专注于写作本身 ✍️
在开始之前,先搞明白我们要做什么
先来理解一下整个自动化流程,其实就像一条”流水线”:
1 | 你写好 Markdown 文章 |
简单来说:你只管写文章、推代码,剩下的事情交给机器人。
第一步:理解”两个分支”的概念
这一步不需要你操作什么,但理解它非常重要,不然后面会一头雾水。
我们会在同一个 GitHub 仓库里使用两个分支:
| 分支 | 存什么 | 谁来管 |
|---|---|---|
source |
博客源码(你写的 Markdown 文章、配置文件等) | 你来管 |
main |
生成的静态网页(HTML/CSS/JS) | 机器人自动管 |
🤔 为什么要分两个分支?
你可以这样理解:
source分支是你的**”厨房”,放着原材料(Markdown 文章、配置文件);main分支是“餐桌”**,放着做好的菜(编译好的网页)。GitHub Pages(也就是展示你博客的服务)只看”餐桌”上有什么。而你平时只需要在”厨房”里干活——写文章、改配置。至于”把菜端上桌”这件事,GitHub Actions 会帮你自动完成。
所以这两个分支不需要合并,它们的内容完全不同——一个是原材料,一个是成品,各管各的。
第二步:更新 .gitignore 文件
在推送源码之前,我们需要告诉 Git:”有些文件不需要上传”。
用编辑器打开项目根目录下的 .gitignore 文件(如果没有就新建一个),把内容改成这样:
1 | .DS_Store |
逐行解释一下:
.DS_Store/Thumbs.db:macOS 和 Windows 系统自动生成的缓存文件,没用db.json:Hexo 的数据库缓存文件,每次hexo generate都会重新生成*.log:日志文件,不需要上传node_modules/:依赖包文件夹,体积巨大(几百 MB),别人拿到你的源码后执行npm install就能自动下载,所以不用上传public/:Hexo 生成的静态文件,机器人会在云端重新生成,不需要上传.deploy*/:Hexo 部署时产生的临时文件夹
第三步:创建 GitHub Actions 工作流文件
这一步是整个自动化的核心——我们要写一个”剧本”,告诉 GitHub 的机器人该怎么帮我们部署。
首先,在项目根目录下创建文件夹和文件:
1 | 📁 你的博客项目/ |
💡
.github/workflows/是 GitHub Actions 的固定路径,GitHub 会自动识别这个目录下的.yml文件并执行。
然后,在 deploy.yml 里填入以下内容:
1 | name: Deploy Hexo Blog |
别被这一大段吓到,我来逐块解释:
触发条件(
on部分):
push+branches: source:只有当你往source分支推送代码时,才会触发这个流程。推到其他分支不会有反应。运行环境(
runs-on):
ubuntu-latest:GitHub 提供的免费云服务器,用的是最新版 Ubuntu 系统。相当于 GitHub 借你一台电脑用一会儿。步骤详解(
steps部分):
- Checkout source:把你的源码从 GitHub 下载到这台云服务器上。
fetch-depth: 0表示获取完整的历史记录(这一点很重要,后面第 2 步要用到)。- Restore file modification time(⚠️ 重要!):恢复每个文件的真实修改时间。详细解释见下面的「踩坑提醒」。
- Setup Node.js:在云服务器上安装 Node.js 20 版本。
cache: 'npm'会缓存依赖,下次构建更快。- Install dependencies:执行
npm ci安装依赖。这和你本地的npm install类似,但更适合自动化环境(更干净、更快)。- Generate static files:先清理旧文件,再生成新的静态网页,和你本地手动执行的命令一模一样。
- Deploy to GitHub Pages:把
public/文件夹里生成的内容,推送到main分支。
github_token:这是 GitHub 自动提供的令牌,你不需要额外配置,它让机器人有权限往你的仓库推送代码。publish_dir: ./public:告诉机器人要部署的是public文件夹(Hexo 生成的静态文件都在这里)。publish_branch: main:部署目标是main分支。
⚠️ 踩坑提醒:为什么需要”恢复文件修改时间”这一步?
Hexo 默认用文件的系统修改时间(mtime)来生成文章的”更新于”时间。但 Git 有个特点:它不会保存文件的原始修改时间。当 GitHub Actions 的机器人执行
checkout(检出代码)时,所有文件的修改时间都会被设为检出那一刻的时间——也就是说所有文章的”更新于”会变成同一个时间!第 2 步的脚本通过
git log查询每个文件最后一次被提交的时间,再用touch -d把文件的修改时间恢复回去,这样 Hexo 就能拿到正确的更新时间了。其中
git config core.quotePath false这一行也很关键——Git 默认会把中文文件名转义成\345\237\272...这样的乱码格式,导致touch命令找不到文件。关闭这个选项后,文件名就会正常输出中文了。这也是为什么第 1 步的
fetch-depth: 0不能省略——它确保拉取了完整的 Git 历史,git log才能查到每个文件真正的最后修改时间。
第四步:在 GitHub 上配置权限
工作流文件写好了,但还需要在 GitHub 上开一个”门禁”,让机器人有权限往仓库里推送代码。
- 打开你的 GitHub 仓库页面(比如
https://github.com/你的用户名/你的用户名.github.io) - 点击上方的 Settings(设置)
- 在左侧菜单找到 Actions → General
- 往下滚动,找到 Workflow permissions(工作流权限)
- 选择 Read and write permissions ✅
- 点 Save 保存
📌 这一步的作用是:允许 GitHub Actions 机器人往你的仓库写入内容(也就是把生成的网页推送到
main分支)。默认情况下机器人只有”读”的权限,没有”写”的权限。
第五步:确认 GitHub Pages 的设置
确保 GitHub Pages 知道该从哪个分支读取网页内容。
- 还是在仓库的 Settings 页面
- 在左侧菜单找到 Pages
- 在 Build and deployment 下面:
- Source 选择
Deploy from a branch - Branch 选择
main,目录选/ (root)
- Source 选择
- 点 Save 保存
这一步告诉 GitHub Pages:”请从
main分支的根目录读取网页文件来展示。”
第六步:推送源码到 GitHub
万事俱备,现在把你的博客源码推到 GitHub 上吧!
打开终端(Git Bash),进入你的博客项目目录,然后依次执行以下命令:
1 | # 进入你的博客项目目录 |
1 | # 初始化 Git 仓库(如果你之前已经 git init 过了,会提示 Reinitialized,没关系) |
git init的作用是在当前文件夹里创建一个 Git 仓库,让 Git 开始管理这个项目的所有文件变动。
1 | # 关联远程仓库 |
git remote add origin的意思是:给这个本地项目”绑定”一个远程 GitHub 仓库,origin是远程仓库的别名(约定俗成就叫这个名字)。⚠️ 如果提示
fatal: remote origin already exists.,说明之前已经绑过了,可以跳过这一步,或者先执行git remote remove origin再重新绑定。
1 | # 创建并切换到 source 分支 |
git checkout -b source做了两件事:创建一个名为source的新分支,并切换到这个分支上。以后你的所有操作都在source分支上进行。
1 | # 把所有文件加入暂存区 |
git add .的意思是:把当前目录下所有改动过的文件都标记为”准备提交”(.代表当前目录下的所有文件)。被.gitignore列出的文件会自动排除。
1 | # 提交到本地仓库 |
git commit -m "消息"的意思是:把暂存区的文件正式保存到本地仓库,-m后面引号里的内容是这次提交的说明,方便以后回看。
1 | # 推送到 GitHub 的 source 分支 |
git push就是把本地的代码上传到 GitHub。-u origin source的意思是:推送到远程仓库origin的source分支,并且设置为默认推送目标(以后直接git push就行了,不用再写后面那一串)。
推送完成后,去你的 GitHub 仓库页面看一下:
- 切换到 Actions 标签页,你应该能看到一个正在运行的工作流(小黄圈转啊转的🟡)
- 等它变成绿色的勾 ✅,就说明部署成功了!
- 打开你的博客网址
https://你的用户名.github.io,确认一下页面是否正常
🟡 第一次运行可能需要 1-2 分钟,耐心等待就好。
以后发布新文章的流程
配置完成后,以后每次写新文章,只需要三步:
1 | # 1️⃣ 创建新文章 |
就这么简单!推送后等 1-2 分钟,刷新博客页面就能看到新文章了 🎉
再也不用手动 hexo clean && hexo generate && hexo deploy 了~
💡 常见问题
Q1:source 和 main 两个分支需要合并吗?
不需要,也不能合并。
这两个分支虽然在同一个仓库里,但它们的内容完全不同:
source存的是源码(Markdown 文件、配置文件等),是”原材料”main存的是生成的网页(HTML/CSS/JS),是”成品”
如果你把 source 合并到 main,GitHub Pages 就找不到正确的网页文件了,博客会直接挂掉。
它们是平行存在、互不干扰的关系。你只需要关心 source 分支,main 分支交给机器人自动管理就好。
Q2:为什么用同一个仓库的两个分支,而不是两个仓库?
用同一个仓库更方便:
- 管理简单:一个仓库搞定所有事情
- 权限方便:GitHub Actions 天然有权限操作同一个仓库的所有分支,不需要额外配置 Token
- 社区惯例:这是 GitHub Pages 博客最常见的做法
Q3:部署失败了怎么办?
- 去 GitHub 仓库的 Actions 页面查看失败的工作流
- 点进去看具体的错误日志
- 常见原因:
- 权限问题:检查第四步的 Workflow permissions 是否设置成了 Read and write
- 依赖安装失败:检查
package.json是否正确 - 分支名不对:确认工作流文件里的分支名和你实际推送的分支名一致
Q4:我能不能在本地预览文章再推送?
当然可以!推送之前先在本地看看效果:
1 | npx hexo server |
然后打开浏览器访问 http://localhost:4000 就能预览了。确认没问题后再推送。
🎉 总结
恭喜你!现在你的博客已经实现了全自动部署。整个流程就是:
写文章 → git push → 自动部署 → 博客更新
你需要做的,就只是专注于写作本身了。
希望这篇教程对你有帮助,如果遇到问题欢迎留言交流~