hexo
中有著豐富的主題可以選擇, 大部分的使用示例或者教程都是將主題 clone 到 theme 資料夾中來使用. 但這樣來使用主題會存在如下的問題:
- theme 中的主題屬於一個獨立的 Git 專案, 有自己的
.git
專案資料夾, 提交 hexo 專案時預設不會提交 theme 的.git
資料夾, 在其他電腦上 clone 後會失去 theme 原本的版本控制功能. - 使用自己修改的主題時, 每次更改完主題, 需要在主題資料夾中提交一次, 然後再在 hexo 專案根資料夾中提交一次, 會產生兩次修改內容一樣的提交, 不夠優雅.
還好萬能的 Git 針對這種問題已經有了成熟的解決方案, 通過自帶的 Git submodules 功能即可優雅的避免以上的問題.
Git submodules 簡介
Git submodules 稱之為 Git 子模組. 子模組允許你將一個 Git 倉庫作為另一個 Git 倉庫的子目錄. 它可以讓你將另一個倉庫克隆到自己的專案中, 同時還保持提交的獨立. 它非常適合我們程式設計師在專案管理時遇到的一種情況: 某個工作中的專案需要包含並使用另一個專案. 這些包含的專案也許是第三方庫, 或者你獨立開發的, 用於多個父專案的庫. 你想要把它們當做兩個獨立的專案, 同時又想在一個專案中使用另一個.
在 hexo 中使用豐富的第三方主題的情況正非常符合這種情景.
Git submodules 使用
瞭解了 Git submodles 的使用場景後, 這麼強力的工具如何在 hexo 中來使用呢. 在這裡演示下我的用法.
首先初始化一個用來演示的 hexo 專案:
npm install hexo-cli -g
hexo init blog
cd blog
npm install
hexo server
複製程式碼
執行以上操作後, 開啟瀏覽器進入 http://localhost:4000/ 便可以預覽到初始化好的 hexo 頁面. 在專案的 theme
資料夾中可以看到使用了預設的 landscape
主題. 在這個 hexo 專案中建立起 Git 版本管理.
git init
git commit -m 'initial project'
複製程式碼
現在一個 hexo 本地倉庫已經建立好了並將初始化的檔案提交了進去.
基礎用法
現在我們使用 Git submodules 的方式來選擇一個第三方主題來替換原本的 landscape
主題. 這裡選擇我比較喜歡的的 pure 主題.
git submodule add https://github.com/cofess/hexo-theme-pure themes/pure
複製程式碼
git 便會將 hexo-theme-pure
主題作為一個專案子模組 clone 到 themes/pure 中. 同時 hexo 專案中會自動生成一個 .gitmodules
檔案, 這個配置檔案中儲存了專案 URL 與已經拉取的本地目錄之間的對映.
.gitmodules 檔案內容
$ cat .gitmodules
[submodule "themes/pure"]
path = themes/pure
url = https://github.com/cofess/hexo-theme-pure
複製程式碼
git 目前狀態
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitmodules
new file: themes/pure
複製程式碼
可以看到, 雖然 themes/pure 是工作目錄中的一個子目錄, 但 Git 還是會將它視作一個子模組. 當不在那個目錄中時, Git 並不會跟蹤它的內容, 而是將它看作該倉庫中的一個特殊提交.
主題 clone 好後, 按照主題的說明安裝好需要的外掛模組, 再執行 hexo s
, 重新開啟 http://localhost:4000/ 便可以看到使用新主題的部落格頁面了.
提交新的 git 記錄
$ rm -rf themes/landscape
$ git commit -am 'added pure themes'
create mode 100644 .gitmodules
create mode 160000 themes/pure
複製程式碼
刪除舊的 landscape
主題, 使用 git commit -am
重新提交新增了 pure
主題的 hexo 專案, 可以看到 git 使用 160000 模式建立 themes/pure 記錄. 這是 git 中的一種特殊模式, 它本質上意味著將一次提交記作一專案錄記錄, 而非將它記錄成一個子目錄或者一個檔案.
拉取含子模組的修改
主題作為子模組新增到專案中後, 若主題作者有更新, 便可通過兩種方法來拉取主題的更新內容.
- 進入
themes
下主題目錄, 執行git fetch
和git merge origin/master
來 merge 上游分支的修改 - 直接執行
git submodule update --remote
, Git 將會自動進入子模組然後抓取並更新
更新後重新提交一遍, 子模組新的跟蹤資訊便也會記錄到倉庫中.
拉取含子模組的專案
使用 git clone
命令預設不會拉取專案中的子模組, 在 clone 後的專案中可以通過執行兩個命令:
git submodule init
初始化本地配置檔案git submodule update
從該專案中抓取所有資料並檢出父專案中列出的合適的提交
也可在 clone 使用 git clone --recursive
命令, git 就會自動初始化並更新倉庫中的每一個子模組.
高階使用
通過子模組基礎用法, 可以直接方便的跟蹤管理一些的簡單的主題. 但很多主題都存在一些自己的配置專案, 需要我們根據自己的需要來進行設定, 或者我們想要在主題的基礎上自定義修改自己喜歡的主題, 這個時候就需要對主題進行修改並提交倉庫以便在各處使用.
不過對於主題倉庫我們一般沒有提交的許可權, 不能提交到主題源倉庫中. 此時可以通過 fork
功能, 在源主題上 fork 出自己專案, 從而在自己倉庫中進行提交來跟蹤修改.
這裡我在 pure 主題上 fork 出了一個自己的主題倉庫 my-hexo-theme-pure, 使用這個倉庫按照之前的步驟替換原本的主題來作為子模組.
修改子模組
當執行 git submodule update
從子模組倉庫中抓取修改時, Git 將會獲得這些改動並更新子目錄中的檔案, 但是會將子倉庫留在一個稱作 遊離的 HEAD
的狀態. 這意味著沒有本地工作分支(例如 "master")跟蹤改動, 此時做的任何改動都不會被跟蹤. 因此, 我們首先需要進入子模組目錄然後檢出一個分支.
$ git checkout stable
Switched to branch 'stable'
複製程式碼
若子分支倉庫中有未同步的更新, 可通過 git submodule update --remote --rebase
來同步最新的內容. 之後便可以開啟編輯器在子模組上工作修改程式碼了.
同步源主題的修改
主題作者釋出了新的主題功能或者修復了Bug, 我們想同步到自己的自定義主題當中. 因為我們的自定義主題是從原主題中 fork 出來的, 可以通過 git remote add source https://github.com/cofess/hexo-theme-pure
命令將源主題倉庫新增為子模組的 一個新的 source
倉庫. 然後執行 git fetch
拉取修改後, 便可以通過 git merge origin/master
來同步源主題的更新了.
釋出子模組的修改
子模組修改完成後, 我們便可以釋出到倉庫中, 以便在其他地方重新 clone 時可以使用最新的主題檔案. 為了防止我們遺忘子模組的提交, 可以在 push 時通過 git push --recurse-submodules=check
命令, 如果任何提交的子模組改動沒有推送那麼 check 選項會直接使 push 操作失敗.
另外也可以使用 git push --recurse-submodules=on-demand
git 會自動嘗試推送變更的子專案.
擴充用法
以上介紹了使用子模組來管理 themes 的方法, 實際上在 hexo 中還可以使用 子模組來管理 hexo 的靜態部署檔案. 對於使用 github 託管靜態頁面等部署方式的使用者而言, 通過 hexo-deployer-git
外掛可以方便的自動化部署靜態頁面.
hexo-deployer-git 工作流程
hexo-deployer-git
部署的方式是在 hexo 專案根目錄下建立了一個 .deploy_git
資料夾, 並在其中建立了一個獨立的 git 分支, 將生成靜態檔案移入這個資料夾中並推送到指定的地址. 但 .deploy_git
資料夾預設也被寫入 .gitignore
檔案中, hexo 專案 git 庫不會記錄這個資料夾, 同時 hexo-deployer-git
在每次部署時也不會自動同步伺服器上的提交歷史, 而是強制覆蓋舊的提交. 在新的電腦或路徑上重新 clone 後也會出現舊的靜態檔案記錄丟失的情況, 重新 deploy 後伺服器上舊的部署歷史也會丟失.
如果想要儲存每次的部署記錄, 那麼就可以將 .deploy_git
中的檔案也看做一個子專案, 以子專案的形式提交到 hexo 主專案中儲存, 就可以保持部署記錄不丟失, 並且在任何地方重新 clone 時都可以恢復最新的記錄.
新增 .deploy_git 中分支為子專案
.deploy_git
中是由部署外掛在 hexo 專案上建立的一個獨立分支, 只需通過傳遞 -b
選項將 hexo 專案的這個分支作為主專案的依賴即可, 例如部署在 coding
時, 使用的 coding-pages
分支:
git submodule add -b coding-pages <site>
複製程式碼
參考資料
Pro Git book - 子模組 git-scm.com/book/zh/v2/…