此次学习子模块就是因为公司的基础框架在多个不同的项目上的使用,同时又想当在开发项目过程中对基础框架有改动时,其他项目也能同时更新到改动的部分,而子模块允许我们将一个git仓库作为另一个git仓库的子目录,同时还能保持提交独立,正好满足原来设想的需求。
git submodule add https://github.com/yangmin1234/test1.git
当我们运行 git submodule update 从子模块仓库中抓取修改时,Git 将会获得这些改动并 更新子目录中的文件,但是会将子仓库留在一个称作 “游离的 HEAD” 的状态。 这意味着没有本 地工作分支(例如 “master”)跟踪改动。 所以你做的任何改动都不会被跟踪。
git checkout stable进入子模块并检出相应的工作分支
git submodule update --remote从上游拉取数据
git submodule update --remote --merge 从上游拉取数据并合并
发布子模块改动
如果我们在主项目中提交并推送但并不推送子模块上的改动,其他尝试检出我们修改的人会遇到 麻烦,因为他们无法得到依赖的子模块改动。 那些改动只存在于我们本地的拷贝中。
为了确保这不会发生,你可以让 Git 在推送到主项目前检查所有子模块是否已推送。 git push 命令接受可以设置为 check 或 on-demand 的 --recurse-submodules 参数。 如果任何提交的子模块改动没有推送那么 check 选项会直接使 push *** 作失败。
提交主项目时自动检测子模块是否有未提交的改动
git push --recurse-submodules=check
提交主项目时,尝试自动推送一改动的子模块
git push --recurse-submodules=on-demand
子模块技巧
子模块遍历
有一个 foreach 子模块命令,它能在每一个子模块中运行任意命令。 如果项目中包含了大量子模块,这会非常有用。
有用的别名
你可能想为其中一些命令设置别名,因为它们可能会非常长而你又不能 设置选项作为它们的默认选项。
子模块的问题
例如在有子模块的项目中切换分支可能会造成麻烦。 如果你创建一个新分支, 在其中添加一个子模块,之后切换到没有该子模块的分支上时,你仍然会有一个还未跟踪的子模块目录。
子模块 *** 作
git submodule add https://github.com/yangmin1234/test.git #将一个git仓库作为本仓库的一个子目录
git clone https://github.com/yangmin1234/test2.git clone带子模块的项目
git submodule init
git submodule update
git push --recurse-submodules=check 提交主项目时自动检测子模块是否有未提交的改动
git push --recurse-submodules=on-demand 提交主项目时,尝试自动推送一改动的子模块
在这篇文章中,我们来讲解一下 git submodule 的实战用法,包括:
假设我们有主仓库 main-module.git ,远程地址 https://github.com/bitmingw/main-module.git ,目录结构
以及仓库 sub-module.git ,远程地址 https://github.com/bitmingw/sub-module.git ,目录结构
如果想要将仓库 sub-module.git 注册成为主仓库 main-module.git 的一个子模块,可以使用如下指令:
git 会自动从远程服务器 clone sub-module.git ,之后 main-module.git 的目录会变成这个样子
由于添加 git 子模块的 *** 作本身也是一个提交,因此它仅仅对 main-module.git 的当前分支有效,另外的分支不会感知到这一变化。
大多数时候, git 子模块 不是凭空创建的,而是从项目中已有的文件拆分出来的。从已有的文件创建 git 子模块 需要做三件事:首先为拆分出来的文件创建新的 git 仓库 ,然后从主仓库中将独立出去的文件移除,最后再注册 git 子模块
例如,假设 main-module.git 的目录结构如下所示
它有 v1.0 和 v2.0 两个分支,在 v2.0 分支中,我们想让 sub-module 文件夹变成 sub-module.git 子模块。
,为 sub-module 创建一个单独的 git 仓库:
,从 main-module.git 中删除 sub-module 文件夹:
,将 sub-module.git 注册为 main-module.git 的子模块
如果你是主仓库的开发者,你可能不想使用最新版本的子模块,而是使用主仓库中指定版本的子模块,此时可以使用下面的指令:
在使用该指令前,主仓库和子模块的 git status 分别是:
使用了 git submodule update 之后,两个仓库的 git status 信息变成了这个样子:
这样,主仓库的开发者就可以从一个干净的空间开始工作了。
还记得我们是从 v2.0 分支引入子模块的么?假如现在要查看 v1.0 分支,会发生什么呢?
还记得我们是从 v2.0 分支引入子模块的么?假如现在要查看 v1.0 分支,会发生什么呢?
难道有了子模块之后我们就回不去了??情况没有那么糟糕,我们可以通过 git checkout -f v1.0 强行回去。
不过这个时候要注意,由于 sub-module 没有被移除,因此切换到 v1.0 分支 以后,你看到的 sub-module 文件夹依然是个子模块。也就是说,子模块穿越了时空来到了 v1.0 分支 …… 嗯这个行为似乎不是我们期望的那个样子。
如果你真的想回到 v1.0 分支 的非子模块的 sub-module ,那你不得不在切换分支前把这个子模块卸载掉:
如果你想从 v1.0 分支 回到 v2.0 ,也会遇到一些问题。
经过了 git checkout -f v1.0 和 git checkout v2.0 之后,子模块的文件竟然被 git 删掉了。而且这个时候无论是 git submodule update 还是 git checkout -- sub-module 都不好使了。到底应该怎么办呢?
答案是在子模块内部使用 git reset 。
从这一部分的演示可以看出, git submodule 的设计对从已有文件拆分出来的子模块来说是非常糟糕的。或许这会成为大家尽量避免使用 git 子模块 的原因之一吧。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)