暴力而不失优雅地升级Hexo主题

对hexo页面排版的改动时常需要改主题目录里的文件,但主题也会升级,这意味着用户和主题开发者可能会改动相同的代码,如果不妥善管理代码,需要升级主题时,可能会很不优雅。本文以Next主题为例。

手动升级

面对升级版本之间的改动,一种容易想到的方法是纯手动升级。这里有两个案例

  1. Hexo 主题快速升级办法-知识沉言

    手动保存主题改动过的文件
    如果你在themes/xxx主题文件有自定义的修改,请自行手动备份一下;如果你是大改的话,我也没有好办法

  2. Hexo升级之坑-杨二小

    断断续续折腾了两天,才升级成功。所以,如果有啥感想,那就是:没事别瞎TM升级!当然,如果一定要升级,最好做增量升级:另起炉灶,一项一项地加功能,这样好定位问题,也容易回滚。

看来手动升级不够优雅,容易采坑。

通过git升级

为了避免手动升级,一个思路是采用git仓库管理主题目录,当主题升级时,采用git进行平滑升级。
这看似优雅,却会引入另一个问题:如何在主博客仓库中合理管理一个子主题仓库?NexT Issue #932有很多讨论,也有一些解决方案,这里列出几个:

1 采用数据文件的方式

参考数据文件的介绍NexT Issue #328。采用数据文件也只能避免_config.yml文件冲突,对于用户修改页面模板情况就没办法了。

2 基于fork + submodule

维护父子两个仓库大大增加了复杂度,还要fork一份冗余的主题仓库,为了不经常有的主题升级增加这样的复杂性,实在没什么必要。

3 同步工具

有用户写了一个hexo同步工具hexo-git-backup,支持博客、主题的同步,支持自定义commit消息。但本质上是个备份工具,需要删除掉主题目录的.git目录,所以也不支持通过git升级主题。

采用git升级的方式,确实能够解放双手,平滑升级,但毕竟还是引入了一定的复杂度。有没有一种既能利用git的平滑升级,又不那么复杂的方案?

暴力但不失优雅的解决方式

由于主题升级的次数相对较少,一般不如用户修改频繁,所以一种简单易行暴力的方式是,git只用来升级,不用来同步,既能利用git进行平滑升级,又避免了引入双层git的复杂情况。

原理

由hexo博客主目录作为git仓库统一管理所有代码,主题目录不设单独git仓库。每次升级主题时,手动将主题目录制作成临时的git仓库,进而以git的方式进行升级,升级过后可以再销毁这个临时git仓库,由博客主仓库管理升级变更。

步骤

  1. 记录当前的主题版本tag,版本号在主题目录的package.json中的version字段。
  2. 随便找个其他目录,clone最新版本的主题仓库,新建分支temp并checkout,再将temp分支reset –hard到当前版本的tag。
  3. 【暴力】确认hexo的主题目录中没有.git目录,如果有,删掉。此时拿到步骤2的temp分支对应的.git文件夹,将其拷贝到hexo的主题目录中。
  4. 在主题目录中的temp分支上做一次提交(这次提交代表着在上一个版本基础上对主题目录所做的所有更改)。
  5. 在temp分支上merge想要升级到的版本tag,如果有冲突逐一解决掉。
  6. 至此升级完成,主题目录下的.git可以删掉了(销毁临时git仓库)。升级完成后记得将主目录做一次提交,主目录会将主题升级的所有改动进行提交。

特殊情况——NexT从v5.1.x升级到v6.0.x

NexT从v5.1.x升级到v6.0.x比较特殊,涉及到代码仓库的更改,代码仓库从iissnan改为theme-next。官方推荐这种方式:Update from NexT v5.1.x ,但这种方式治标不治本,保留了iissnan仓库的主题,新建了来自theme-next仓库的主题,做了一个切换而已;而迁移的过程,还是依赖手动,并没有利用类似git merge的平滑升级。
由于本文方法并不强依赖于git提交的连续性,而是只需要临时制作一个git仓库即可,所以天然支持这种更换git仓库的升级。

本文方法稍加改动就可以适用于NexT从v5.1.x升级到v6.0.x,具体步骤:

  1. 利用iissnan仓库的.git目录,将主题升级到iissnan仓库的最终版本。
  2. 利用theme-next仓库的.git目录,承接后续的升级。

注意

NexT v6.5.0主题仓库的.gitignore默认忽略了lib/里的font-awasome等内容(其他版本没有了解),如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.DS_Store
.idea/
*.log
*.iml
yarn.lock
package-lock.json
node_modules/

# Ignore unused verdors' files
source/lib/fancybox/*
!source/lib/fancybox/source/

source/lib/font-awesome/less/
source/lib/font-awesome/scss/

source/lib/ua-parser-js/*
!source/lib/ua-parser-js/dist/

source/lib/Han/*
!source/lib/Han/dist/

这带来一个问题,如果主题仓库不是fork来的,而是想用主目录统一管理博客源代码,font-awesome等内容将无法推送到远程仓库,导致在其他环境从远程仓库clone时拿不到font-awasome,进而页面显示不正常。所以这里注意一下,主题.gitignore文件里的内容该删的删,该改的改。