# 添加子模块 [1]
命令格式:
git submodule add <仓库地址> <本地路径> |
以我博客主题 shoka 的 Fork
版本为例
仓库地址
可以是 https
或者 ssh
链接:
https://github.com/llxlr/hexo-theme-shoka.git |
git@github.com:llxlr/hexo-theme-shoka.git |
我实际用到的命令:
git submodule add -b dev --name shoka git@github.com:llxlr/hexo-theme-shoka.git themes/shoka | ||
Cloning into 'C:/Users/i/Desktop/blog/themes/shoka'... | ||
remote: Enumerating objects: 2278, done. | ||
remote: Counting objects: 100% (239/239), done. | ||
remote: Compressing objects: 100% (160/160), done. | ||
remote: Total 2278 (delta 100), reused 153 (delta 68), pack-reused 2039Receiving objects: 96% (2187/2278), 3.Receiving objects: 98% (2233/2278), 3.60 MiB | 2.17 MiB/s | ||
Receiving objects: 100% (2278/2278), 3.66 MiB | 2.19 MiB/s, done. | ||
Resolving deltas: 100% (1232/1232), done. | ||
warning: LF will be replaced by CRLF in .gitmodules. | ||
The file will have its original line endings in your working directory |
子模块数据包含在以下目录结构:
tree . | ||
. | ||
├── .git | ||
│ ├── config | ||
│ └── modules | ||
│ └── shoka | ||
├── .gitmodules | ||
└── themes | ||
└── shoka |
以下为子模块信息( .git/config
文件亦包含 .gitmodules
同样的内容)
[submodule "shoka"] | |
path = themes/shoka | |
url = git@github.com:llxlr/hexo-theme-shoka.git | |
branch = dev |
通过 -b
选项指定了 dev
分支(复制于 master
分支), --name
选项指定了子模块名称为 shoka
。
也可以使用以下命令指定分支:
git config -f .gitmodules submodule.shoka.branch dev | ||
git submodule update --remote |
#检出
克隆一个包含子模块的仓库,并不会 clone
子模块的文件,只是会克隆 .gitmodule
描述文件,需要进一步克隆子模块文件。
git submodule update --init --recursive # 能同时拉取子模块 / 嵌套的子模块 |
git submodule init # 初始化本地配置文件 | ||
git submodule update # 检出父仓库列出的 commit |
# 提交子模块
提交变更信息:
git commit -am 'add themes/shoka module' | ||
[master (root-commit) e56f4c4] add themes/shoka module | ||
2 files changed, 5 insertions(+) | ||
create mode 100644 .gitmodules | ||
create mode 160000 themes/shoka |
推送到远端:
git push origin master |
# 更新子模块
如果远端有子模块的新提交,需要本地更新数据:
cd themes/shoka | ||
git pull | ||
cd ../../ |
# 删除子模块
- 删除
.gitsubmodule
文件里相关部分 - 删除
.git/config
文件里相关部分 - 删除子模块目录
blog git rm --cached <本地路径>
若未按照上述步骤删除子模块,在
.git/modudles
文件夹内可能有残留。
# 变更子模块平台 [2]
当子模块项目改变了它的托管平台,比如从 GitHub 迁移到公司 GitLab/Gitea/Gogs 服务器。
git submodule sync --recursive # 将新的 URL 复制到本地配置中 | ||
git submodule update --init --recursive # 从新 URL 更新子模块 |
# 在子模块中工作
比如从本地子模块检出一个分支 stable
:
cd themes/shoka | ||
git checkout stable | ||
Switched to branch 'stable' |
尝试用 --merge
选项来更新子模块。这时将会看到服务器上的这个子模块有一个改动并且它被合并了进来。
git submodule update --remote --merge |
当我们对子模块做一些本地的改动而同时其他人推送另外一个修改到上游时,在此时更新子模块,就会看到我们在本地做了更改时上游也有一个改动,需要将它并入本地。
git submodule update --remote --rebase |
若忘记 --rebase
或 --merge
,Git 会将子模块更新为服务器上的状态,并且会将项目重置为一个游离的 HEAD
状态。
git submodule update --remote |
# 子模块技巧
# 遍历
若开始开发一项新功能或者修复一些错误,并且需要在几个子模块内工作。
我们可以轻松地保存所有子模块的工作进度。
git submodule foreach 'git stash'
能够生成一个主项目与所有子项目的改动的统一差异
git diff; git submodule foreach 'git diff'
# 别名
为命令设置别名,因为它们非常长而又不能设置选项作为它们的默认选项。
若计划大量使用子模块,这样当你想要更新子模块时可以简单地运行 git supdate
,或 git spush
检查子模块依赖后推送。
git config alias.sdiff '!'"git diff && git submodule foreach 'git diff'" | ||
git config alias.spush 'push --recurse-submodules=on-demand' | ||
git config alias.supdate 'submodule update --remote --merge' |
# 在其他电脑上维护博客
此时当前博客仓库内包含着 shoka
子模块,需要指定 --recurse-submodules
选项,以便在克隆项目的同时递归拉取子模块:
git clone --recurse-submodules git@github.com:llxlr/blog.git |
若未指定 --recurse-submodules
选项,参考 检出