如果你的代码有依赖于某些第三方组件,而这些第三方组件又是常用的,例如模板、邮件、office等,建议把这些组件放到git的submodule里面,组件单独形成一个repo。

正好最近有用到Git Submodule,下面整理一下它的相关用法。

举个例子,假如说submodule所在的repo地址为https://yourcustomsite.com/test/mysubmodule

添加子模块

那么可以用以下命令把子模块加入到其中

git submodule add https://yourcustomsite.com/test/mysubmodule

这个命令执行完成之后,就会在你的项目里新增了mysubmodule文件夹和.gitmodules文件。

默认情况下,子模块的目录是与仓库同名的。如果想要指定别的目录名字othername,那么可以这样:

git submodule add https://yourcustomsite.com/test/mysubmodule othername

一般情况下是成功的,有时候可能不成功是因为系统会提示你是否确认要更改子模块目录名,或者当前目录已经有同名子模块了 ,这个你可以你自己斟酌,可以加上--force强制或者--name 设置目录名

git submodule add --force https://yourcustomsite.com/test/mysubmodule othername

如果你这个submodule的repo有好几个分支,你想用其中的某个分支mybranchname,不想用默认的master分支,那么可以使用-b来指定分支名称。

git submodule add -b mybranchname --force https://yourcustomsite.com/test/mysubmodule othername


去除子模块

假如说按照下面这个命令加入子模块

git submodule add -b mybranchname --force https://yourcustomsite.com/test/mysubmodule othername

如果想要删除子模块,则使用命令git submodule deinit othername就能够去除本地的子模块文件,如果要删除远程的文件,还需要执行命令git rm -r othername,这样也把当前项目的远程仓库里的子模块给删除了

url或者branch有改动

假如说按照下面这个命令加入子模块

git submodule add -b mybranchname --force https://yourcustomsite.com/test/mysubmodule othername

那么子模块加载完成后新增的.gitmodules文件的格式是这样的:

.gitmodules文件的内容

[submodule "othername"]
	path = othername
	url = https://yourcustomsite.com/test/mysubmodule
	branch = mybranchname

如果项目里面已经添加了子目录,但是发现url或者branch不对,想要该成果来,那么步骤有以下几个:

  • 步骤一、git submodule deinit othername去除子模块
  • 步骤二、删除.gitmodules文件
  • 步骤三、git rm --cached othername删除本项目仓库里的子模块
  • 步骤四、git submodule add ……添加子模块

有时候操作会有一些提示,比如说

Please stage your changes to .gitmodules or stash them to proceed

一般是因为你没删除.gitmodules文件,就去删远程仓库的子模块了。这个问题的解决办法是:先步骤二、再步骤三

还会有一些提示比如

'othername' already exists in the index

是因为你没有执行步骤三就去执行步骤四了,所以应该先执行步骤三,然后再执行步骤四。

有时候即使按照顺序执行了步骤三、步骤四,但还是会出现xxx already exists in the index的报错,这个时候就要检查一下.git/modules里面是不是已经存在xxx了。

建议rm -rf .git/modules/*


在你把整个项目push到git的时候,git并不会把子模块的代码也放进去,而是会生成一个文件。

比如说你的子模块名字叫othersubname,那么你会在你父项目的文件列表里面看到一个othersubname,它的内容是Subproject commit-id xxxxxx。但如果你把整个父项目clone下来,你是不会看见这个文件的,因为它变成了一个同名文件夹