Git 应该对大家来说使用和了解的很多了,在我的文章列表里面也是写了很多关于 Git 的内容,如果你有兴趣的话,不妨点击左侧的 Archive 查看一下。但是,随着 Git 的不断应用和发展,已经有很多功能存在已久,但是不常为大家所用,或者太难以使用了,例如 Git Submodule 就是这么一个东西。

因为最近我遇到一个和 Go Module 管理相关的问题,查了些资料,发现 Go 的 Module 管理似乎和 Git 的 Module 管理有点类似,所以这里就先看看 Git 的 Module 管理。使用 Git 的 Submodule 步骤还是很简单的,Follow Gitbook 的步骤还是很快可以上手的,下面是一些常用的命令:

虽然添加和克隆子模块很简单,但是子模块的坑还是比较深的,下面就来列举一下。

子模块更新

当拉取一个项目的更新的时候,是不会同时自动拉取子模块的更新的,如果有人更新项目的同时,又更新了子模块并且提交上去了,而你拉更新的时候只是拉取了项目的更新,而没有拉取子模块的更新,那么提交的时候请万分小心,不然可能就是把你本地的子模块版本覆盖掉别人的子模块更新。

这是子模块的坑之一,而你更新子模块是需要进入到子模块的目录下进行更新的。

子模块前套子模块

同样得,如果子模块还依赖着子模块,那么你需要为子模块做同样的事情,去子模块的子模块目录完成代码的拉取。但是,因为这个坑比较常见,所以一般的简单处理方式是通过命令进行:

$ git submodule foreach git pull

更新子模块但是不提交

还有一个坑就是如果有个人更新了子模块和项目,但是却只提交了项目,不提交子模块。这个时候你的项目就会记录你的子模块的版本是一个别人修改了但是未提交的版本记录,无论你怎么更新子模块都是不可能更新成功的。所以,这个时候你能做的就是去查看项目的更新记录,找他做了这件事情的同事,然后进行深刻的“沟通”之后解决。

子模块的游历 HEAD

当你想修改子模块的时候,你是不是认为 cd submodule,然后就可以大肆地发挥你的妙手了?然而,事实上,这是会被打脸的,默认情况下,子模块的 HEAD 是不指向任何有效的 Branch 的,也就是说,你要的第一件事情可能是:

$ cd submodule
$ git checkout master

然后再开始修改,不然的话,你的修改是没有用的。

Reference