前言
大概整理下 git submodule 的用法。
使用场景
在一个项目中,需要使用其它项目,或者想把一些模块抽离出来成为公共模块。除了使用 pod 以外,还可以使用 git submodule 来达成目的。本次主要介绍 sourcetree 里如何进行操作。
基础用法
现有两个项目 submodule-demo 和 module-1, 想在 demo 里使用 module-1。
- clone demo
- Repository -> Add submodule, Source Path/URL 中填入 demo 的仓库地址,Local Relative Path 选择本地 demo 目录下的 module-1 文件夹,然后点击 OK . 生成文件 .gitmodules 和 subproject module-1
git commit
&git push
克隆一个带 submodule 的项目
- clone demo, 有 module-1 文件夹但是是空的
- sourcetree 左侧 submodules , 双击 module-1,进行拉取。命令行操作为
git submodule init
初始化本地配置文件,git submodule update
更新 submodule - 如果 module-1 仓库有更新,双击 module-1,进行更新,HEAD 指向的即为 demo 所依赖的 module-1 版本。可以在本地 module-1仓库里进行 git chekout 指定 branch 或者 commit。
注意
如果其它人在 demo 里的 module-1 进行了变更,但是并没有提交到远程的 module-1仓库,然后又把 demo push,就会把指向本地 module-1 的引用也提交到了远端。此时另外的人在 demo 里进行 git submodule update
时就会报错,找不到当时的引用。
1 | error: Server does not allow request for unadvertised object 857a1126d7a1ad9f91449602f6bb09f8130b2a1d |
此时可以在 demo 下 git log -l module-1
查看 module-1 提交日志找到该人员将 demo 下的 module-1 提交。如果废弃上次提交的话可以重新 checkout 指定 module-1。
优缺点
优点是可以使依赖关系简单明了,但是同样也会有缺点。每次在 demo 里执行 git submodule update
的时候,会获得一个分离的 HEAD 指向提交,容易丢失。例如在 demo 下执行 git submodule update
以后,在 module-1 里不创建分支直接进行提交,如果此时再在 demo 下执行 git submodule update
就会毫无提示的覆盖掉上次的提交。想要找到丢失的提交可以使用 git reflog
. 因此建议在 module-1里新建分支后再进行操作。有两个问题:
如果在有 module-1 的分支上本地提交,切换回没有 module-1 的分支删除 module-1文件夹,再切换回含有 module-1 的分支,会造成 module-1的 HEAD 混乱,需要重新 checkout。
如果在切换回没有 module-1 的分支上后,对 module-1 进行了修改,当前分支不会显示任何提交,切换回含有 module-1 的分支也不会显示有任何提交。但是对该分支 push 以后,会造成
git submodule update
的错误。demo 在新建分支 branch1 上添加 module-1 以后,如果再切换回不带 module-1 的分支,仍然会有一个 module-1 的文件夹。此时要把 module-1 目录删除,当切换回带有 module-1 的分支时要重新 clone。
最后一个问题是如果想把子目录改为 submodule 的形式,需要以下操作。
要先把 module-1 备份提交git! 要先把 module-1 备份提交git! 要先把 module-1 备份提交git!
1
2
3git rm -r --cached module-1
rm -rf module-1
git submodule add module-1.git module-1