为了方便各个子模块独立开发,或使用第三方不断更新的仓库,可以使用子模块来引用.
子模块对应的源码是子模块仓库的克隆.git submodule 与 subtree对比
- git submodule
- 允许其他的仓库指定以一个commit嵌入仓库的子目录
- 仓库 clone下来需要 init 和 update
- 会产 .gitmodule 文件记录 submodule 版本信息
- git submodule 删除起来比较费劲
- git subtree
- 避免以上问题
- 管理和更新流程比较方便
- git subtree合并子仓库到项目中的子目录。不用像submodule那样每次子项目修改了后要init和update 。万一哪次没update就直接add . 将.gitmodule 也 commit上去就悲剧了
- git v1.5.2以后建议使用git subtree
用法
假设P1项目、P2项目共用S项目
1) 关联Subtree 要求working tree是clean的,可以通过git status查看,如果没有staged的东西则可以进行subtree操作.
cd P1项目的路径
git subtree add --prefix=<S项目的相对路径> <S项目git地址> <分支> --squash
解释:--squash意思是把subtree的改动合并成一次commit,这样就不用拉取子项目完整的历史记录。--prefix之后的=等号也可以用空格。 执行这一步时,会clone该子项目的代码到本地,此时通过git log可以查看到如下类似日志:
Squashed 'extern/darknet/' content from commit cdf3200 git-subtree-dir: extern/darknet git-subtree-split: cdf32005c1cf5600be56fe4b35bc1dddc9173b7a
然后执行git push
操作更新到远程,commit日志如下:
Merge commit '34ecafc2a199a9fd3d7ae1facd831156ebc1f860' as 'extern/darknet'
2) 更新代码
P1、P2项目里各种提交commit,其中有些commit会涉及到S目录的更改,但是没关系3) 提交更改到子项目
cd P1项目的路径
git subtree push --prefix=<S项目的相对路径> <S项目git地址> <分支>
Git 会遍历步骤2中所有的commit,从中找出针对S目录的更改,然后把这些更改记录提交到S项目的Git服务器上,并保留步骤2中的相关S的提交记录到S仓库中
4) 更新子目录
cd P2项目的路径
git subtree pull --prefix=<S项目的相对路径> <S项目git地址> <分支> --squash