关于子仓库或者说是仓库共用,git官方推荐的工具是git subtree。 了解了git subtree,感觉比git submodule好用,但是也有一些缺点,在可接受的范围内。
所以对于仓库共用,在git subtree 与 git submodule之中选择的话,我推荐git subtree。
git subtree是什么?为什么使用git subtree
git subtree 可以实现一个仓库作为其他仓库的子仓库。
使用git subtree 有以下几个原因:
- 旧版本的git也支持(最老版本可以到 v1.5.2)
- git subtree与git submodule不同,它不增加任何像
.gitmodule
这样的新的元数据文件 - git subtree对于项目中的其他成员透明,意味着可以不知道git subtree的存在
- git subtree也有它的缺点,但是这些缺点还在可以接受的范围内:
- 必须学习新的指令(如:git subtree)
- 子仓库的更新与推送指令相对复杂
git subtree 的使用
git subtree的主要命令有:
git subtree add --prefix=<prefix> <commit>
git subtree add --prefix=<prefix> <repository> <ref>
git subtree pull --prefix=<prefix> <repository> <ref>
git subtree push --prefix=<prefix> <repository> <ref>
git subtree merge --prefix=<prefix> <commit>
git subtree split --prefix=<prefix> [OPTIONS] [<commit>]
在父仓库中新增子仓库:
在主仓库(或者说是业务仓库)中执行以下命令:
git subtree add --prefix=sub/common http://code.jms.com/xujian/common.git master --squash
--squash
参数表示不拉取历史信息,而只生成一条commit信息。
执行git status
可以看到提示新增两条commit:git log
查看详细修改:
执行git push
把修改推送到远端network-management仓库,现在本地仓库与远端仓库的目录结构为:
多了一个
sub/common
目录
注意:
现在的network-management仓库对于其他项目人员来说,可以不需要知道common是一个子仓库。什么意思呢?
当你git clone
或者git pull
的时候,你拉取到的是整个network-management(包括common在内,libpng就相当于network-management里的一个普通目录);当你修改了common里的内容后执行git push
,你将会把修改push到network-management上。
也就是说network-management仓库下的common与其他文件无异。
从源仓库拉取更新
如果源common仓库更新了,network-management里的common如何拉取更新?使用git subtree pull
,例如:
git subtree pull --prefix=sub/common http://code.jms.com/xujian/common.git master --squash
简化git subtree命令
我们已经知道了git subtree 的命令的基本用法,但是上述几个命令还是显得有点复杂,特别是子仓库的源仓库地址,特别不方便记忆。
这里我们把子仓库的地址作为一个remote,方便记忆:
git remote add -f http://code.jms.com/xujian/common.git
然后可以这样来使用git subtree命令:
git subtree add --prefix=sub/common common master --squash
git subtree pull --prefix=sub/common common master --squash
git subtree push --prefix=sub/common common master
进阶用法:
配合package.json的 workplace
的配置属性,可以做到完全忽略了common子项目的存在。