赞
踩
Git 通过子模块来解决复用模块的问题。 submodule允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。而subtree可以将子模块合并到主模块由主模块完全管理。
Git地址:https://www.git-scm.com/docs/git-submodule
repository_url:克隆子模块的Url地址:ssh/http的都可以,默认拉取master分支
submodule_path: 位于主模块的那个目录位置,默认和src同级,
执行add指令后,主要是两个步骤:
.gitmodule文件:
.git/config文件:
这里就有一个疑问,为啥要将子模块信息放在这两个地方:
执行git ls-tree HEAD查看克隆的子模块文件夹会显示类似这样的信息:
160000 commit d6032c3e83106319e5410738055071954193724a common-web
由于子模块是独立的git仓库,所以每次更新子模块之后要回到主模块,通过git add .来更新主模块对子模块的引用,然后通过commit、push操作,将子模块记录跟着主模块提交到远程,以便其他人拉取主模块时也能获取正确的子模块内容
git add: 如果子模块有更改,会在本地.git配置中更新子模块的应用commit hash…
git commit: 会将子模块的引入和主模块一起commit,即占位的空白文件夹。
克隆主模块之后,子模块是一个空白文件夹,commit类型的引用链接。需要init、update拉取子模块代码
不管在主模块还是在子模块,只要子模块有更新,主模块都要更新子模块的引用才能获取到最新的代码,所以使用git submodule来进行多模块开发进行子模块更新时,一般需要两步:
整体流程图:
PS: 每次更新子模块都要进入子模块,然后回到主模块在更新引用,很麻烦。
// 子模块初始化
git submodule init
// 子模块更新
git submodule update
// 更新某个子模块代码
git submodule update --remote path/to/submodule
// 更新主模块下所有子模块代码
git submodule update --remote
// 子模块更新之后,同步主模块更新子模块的引用commit hash
git add .
// 递归克隆整个项目submodule
// --recursive表示递归地克隆git_parent依赖的所有子版本库。
git clone https://github.com/demo.git assets --recursive
// 递归更新整个项目submodule
git submodule foreach git pull
因为submodule有着每次更新子模块都要进入子模块然后回到主模块并同步主模块更新子模块引用,并且克隆主模块时需要依赖.gitmodule等配置拉取子模块,比较麻烦。为了避免这个,第三方基于Git底层开发了git subtree工具脚步来解决,Git在1.7.11版本后包含在发行版中。
git subtree采用合并的方式,将子模块代码作为普通文件夹直接合并到主模块的目录,这样就提供了主模块完全控制子模块的能力,可以直接在主模块对子模块进行修改更新,然后推送到子模块B的仓库,其他引入模块B的主模块通过更新即可获取最新的模块B代码。然后本地子模块的更新会随着主模块一起上传到远程。
由于是合并的方式,所以主模块会随着引入子模块的增多,而导致主模块代码变得冗余,并且合并子模块也会将子模块所有的历史记录合并到主模块中,会导致主模块历史记录混乱。
随着引入子模块导致主模块代码增多,合理配置目录结构,将子模块和主模块结构清晰划分,更好的管理文件。
子模块合并历史记录导致主模块历史记录混乱:
// 主模块引入子模块
// --prefix 指定了子项目 B 应该放在主项目 A 中的哪个子目录。
// --squash 将子项目 B 的所有历史记录合并为一个提交,以减少主项目 A 的历史记录复杂性。
git subtree add --prefix=path/to/moduleB https://example.com/repoB.git main --squash
// 提交子模块代码
git subtree push --prefix=path/to/moduleB <remote-url> <branch>
// 拉取子模块代码
git subtree pull --prefix=path/to/moduleB <remote-url> <branch>
// 更新主模块下所有子模块代码
git submodule update --remote
上图可知,主要区别:
1、subtree是将子模块合并到主模块中,完全属于主模块,会和主模块一起提交到远程。而submodule是将子模块作为独立仓库通过.gitmodule配置链接到主模块的,主模块提交的是子模块的引用。
2、使用上subtree可以完全受主模块控制,而submodule需要进入子模块然后进行更新,之后再回到主模块同步更新引用。
简单理解为:submodule is link(commit hash), subtree is copy
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。