Git支持子模块,对应的命令集为【git submodule command】,关于子模块的理解,可以参考Git官方的的文档。Git中子模块的意思,就是独立版本控制的项目A中,可能(通过子目录的方式)引用了另一个独立版本控制的项目B。在希望同时使用两个项目的代码时,又希望两个项目的版本控制相互独立。

举例来说,你有一个Android的ROM移植项目,这个项目里需要用到linux内核社区的代码。通常作为移植者,你只希望(通常也只能)对你移植相关的文件进行版本控制,而不希望(也不太可能)对内核代码的版本库进行控制。同时,linux内核的代码,可能具体表现为Android的ROM移植项目下的一个子目录,比如kernel。

这个时候。我们就可以把linux社区的kernel项目,当作你Android的ROM移植项目下的一个子模块。

Git中的子模块并非一个完整的Git版本控制系统。本质上来就是一个对远程版本库的引用,对于远程版本库的tag、branch等特性不提供支持。在子模块中,你可以修改,可以提交,也可以push回去,但是你只能push到你当初clone出来的分支里,不能更改分支,甚至不能标记tag。

对包含子模块的Git项目(我们称之为父项目)而言,子模块的所有改动,父项目不关心改动的内容,只关心改动的状态。对于子模块中没有提交的改动,父项目中体现出来的就是未提交改动。对于已经提交的改动,父项目中体现出来的就是子模块(以目录的形式表现)的索引发生变动。

对此也很容易理解,因为子模块在父项目中,就是一个不需要关心内容,而只需要关心整个目录状态是否改变的子目录。而子模块只是记录对其他项目的某个状态的引用。子模块的使用,初衷就是为了让父项目的各个克隆保持对子模块引用的统一。所以父项目只会关心子模块当前的状态,也就是SHA值了。