最近學習使用 Hugo 構建靜態網站。安裝主題時,接觸到git submodule這個命令,踩了些坑,總結一下。
子模塊與父模塊如何同步更新
子模塊是一個單獨的項目,commit push等操作需要在子模塊自己的repo目錄下操作。父項目的操作與子模塊無關。父項目git add無法添加子模塊的changes,當然也就無法commit push。
子模塊版本升級后,父項目不會自動升級,仍然停留在對之前版本的引用。以下命令可以查看父模塊當前使用子模塊的哪個版本:
> git submodule status
f0dc1cf84d7c47dc1625e956f07b37b6c238a3dc themes/hugo-theme-stack (v3.8.0-4-gf0dc1cf)
 
        子模塊修改后,父模塊雖然無法git add/commit/push,但是git status卻可以顯示:
> git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified:   themes/hugo-theme-stack (new commits)
 
        這里會讓人疑惑,有changes,但是無法add進來。
這是因為,子模塊的修改,只能在子模塊里面進行commit & push。
子模塊commit & push之后,父模塊不會自動更新,仍然保持着對子模塊上一版本的引用。此時可以使用git add submoduleDir 添加子模塊的更新,然后commit & push,將子模塊的修改同步到父模塊。
如果父模塊在尚未add & commit & push子模塊更新的情況下,執行了git submoule update,此時子模塊會回滾到上一版本(父模塊引用的那個版本)。然后去子模塊git status,會提示 HEAD detached at xxxxxx。
如果發生了上述情況,可以在子模塊git branch -a查看分支,git checkout到上次提交修改的分支。然后子模塊就恢復到working tree clean了。
再去父模塊,git add submoduleDir && commit && push。
無法拉取submodule代碼到本地
git clone 了一個包含submodule的倉庫,打開submodule目錄,發現里面是空的:

可嘗試以下命令:
git submodule update
git submodule update --recursive --remote
git submodule update --init
 
        fatal: could not get a repository handle for submodule xxx
這是很常見的錯誤。當上次 clone into 未完成就直接關閉,下次 git submodule update 就會報這個錯。
$ git submodule update --init
Cloning into 'D:/blog/whuwangyong.github.io/themes/FixIt'...
^C
$ git submodule update
BUG: submodule considered for cloning, doesn't need cloning any more?
fatal: could not get a repository handle for submodule 'themes/FixIt'
 
         
         
        解決辦法:將 submodule 路徑下的.git文件刪掉即可。
如何修改子模塊的 remote url
需求:使用的別人的主題repo作為子模塊。然后改了些地方,發現無法提交到父項目,更不能提交到別人的repo。
解決:fork別人的repo,然后使用自己fork的repo作為子模塊。后面原作者的repo更新了,再單獨升級fork后的repo。升級時注意別覆蓋了自己的修改。如果使用良好,不升級也可。
那么,如何將submodule,從引用別人的repo,改為引用自己的。
先刪除
GIT 未提供submodule remove的功能。要刪除一個子模塊,需按照下面步驟操作:
- git submodule deinit sub/module,執行后模塊目錄將被清空。
 - git rm sub/module,執行后會清除.gitmodules里的項目。
 - git commit -m ‘remove sub/module。
 第一步不做似乎也沒關系。第二步是關鍵,這里不能直接rm sub/module,這樣不會同步更新.gitmodules的內容。
再添加
git submodule add https://github.com/whuwangyong/hugo-theme-stack/ themes/hugo-theme-stack
 
        如果遇到如下錯誤:
A git directory for ‘hugo-theme-stack’ is found locally with remote(s): origin https://github.com/CaiJimmy/hugo-theme-stack/ If you want to reuse this local git directory instead of cloning again from https://github.com/CaiJimmy/hugo-theme-stack/ use the ‘–force’ option. If the local git directory is not the correct repo or you are unsure what this means choose another name with the ‘–name’ option.
需刪除本地的緩存:
git rm --cached sub/module 
 
        或直接刪除站點根目錄的.git/module/下面對應的子模塊:
rm -rf .git/module/hugo-theme-stack
 
        然后再次執行git submodule add。
Reference
- GIT 的 SUBMODULE - 閱微堂 (zhiqiang.org)
 - git submodule刪除后重新添加問題_Week Mao的專欄-CSDN博客
 - 來說說坑爹的 git submodule - 掘金 (juejin.cn)
 - Git Submodule_彈吉他的小劉鴨的博客-CSDN博客
 
本文同步發布於:
