子模块
如果想直接上手操作,可以只看 “适用场景”、“定义”、“快速使用” 小节
否则看这篇文章或者 原文 都可以
文章目录
- 子模块
- 适用场景
- 定义
- 快速使用
- 添加子模块
- 同步本地到远程
- 克隆带有子模块的仓库
- 分支操作
- 同步远程到本地
- 相关命令
- 信息补充
- 遇到问题
-
- 未涉及部分
-
适用场景
多个项目依赖一个库,每个项目可以修改库,并且保持库的同步。
定义
广泛的子模块:以A 为一个整体,B 为一个整体。将B 作为 A 中的一部分,即称B 为A 的子模块。
文件结构如下:
A
|-- README.md
|-- B
|-- README.md
父仓库:git 的整体即仓库,故而本文称A 为父仓库。
子模块:同理,B 为子仓库,因为概念为submodule,故而本文称B 为子模块
因为仓库本身是工具型。所以子模块的添加不应该增加或应该较少增加工具使用的负担。因此git 子模块有专门的命令将子模块和父仓库关联,以达到直接在父仓库执行命令操作子模块的便捷性。
但是由于一定的原因,在克隆、同步父仓库的时候,父仓库默认不会操作子模块,即需要使用者额外增加参数或者步骤
同步:因为子模块有个update
的操作,所以仓库的fetch
,pull
,push
操作在这里统一叫做同步
更新:专指 update
本文中【】括起来的文本表示命令,可以在“相关命令” 小节里查看对应的命令语法
如【添加子模块】,直接全文搜索 输入“添加子模块”, 就可以在 “相关命令” 小节看到,且会比使用的地方有更详细的说明
快速使用
父仓库和子模块,各自单独进行自身维护的时候,和常规流程没什么区别。这里不多做说明
主要在于父仓库添加了直接操作子模块的步骤,使得使用更加复杂。
但是关于操作复杂化这一点,熟悉命令之后,可以参考【配置】和【常用别名】进行一波命令优化。
环境 git 2.20.1 (Apple Git-117)
添加子模块
假设当前有两个独立仓库baba,didi,didiUrl 表示didi 的远程地址
希望baba 作为父仓库,didi 作为baba 的子模块
(可能需要 “常见问题” – “忽略文件无效” 小节)
同步本地到远程
现在本地仓库有了子模块,如果要同步,可以有两种方式
克隆带有子模块的仓库
git clone babaUrl
cd didi
git submodule init
git submodule update
cd didiSubmodule
...
上述步骤实在有些繁琐
git clone --recurse-submodules babaUrl
git checkout master
分支操作
现在已经有了 带有didi 子模块的babaWithDidi 仓库
同步远程到本地
现在已经有了 带有didi 子模块的本地 babaWithDidiLocal,克隆自远程的babaWithDidi 仓库
-
本地仓库没有修改
-
babaWithDidi 仓库整体修改
git pull --recurse-submodules
或者
git pull
git submodule update --init --recursive
cd didi
git checkout master
-
didi 修改,而babaWithDidi 没有修改 (其实也属于“babaWithDidi 仓库整体修改”的一种情况)
cd didi
git pull
cd ..
git commit -sa
或者
git submodule update --remote --merge
git commit -sa
-
本地仓库有修改
相关命令
关于命令的格式,参看 命令行格式说明
没有模块名字作为参数的都是处理所有子模块
git config submodule.<submoduleName>.url <URL>
git config --global diff.submodule log
git config status.submodulesummary 1
git config submodule.recurse [1|true]
git config -f .gitmodules submodule.<submoduleName>.branch <branchName>
git config push.recurseSubmodules [check|on-demand]
git config alias.sdiff '!'"git diff && git submodule foreach 'git diff'"
git config alias.spush 'push --recurse-submodules=on-demand'
git config alias.supdate 'submodule update --remote --merge'
git submodule add <submoduleURL> [targetName]//subURL 可以是相对路径也可以是url
git submodule update [--init] [--recursive] //如果没有初始化过,需要init;如果有嵌套,需要recursive
git submodule update --remote [--merge|rebase] //默认master,没有[--merge|rebase]是游离态,要在父仓库使用
git log -p --submodule //展示子模块的修改记录
git diff --cached --submodule
git diff --cached [submoduleName]
git checkout --recurse-submodules
git pull --recurse-submodules
git push --recurse-submodules=[check|on-demand] //check 表示如果子模块有没push的,直接失败;on-demand则先尝试push子模块再失败
git clone --recurse-submodules <srcURL> [targetURL]
git submodule foreach <`gitCommand`>
git submodule foreach 'git stash'
git submodule foreach 'git checkout -b featureA'
git diff; git submodule foreach 'git diff'
信息补充
父仓库和子模块关联之后
-
子模块也会以一种特殊文件模式(160000,表示该文件在提交中,是作为一个目录整体)存储在父仓库的 .git
中。
-
会在父仓库修改或创建 .gitmodules
,这个文件记录了子模块和父仓库的映射关系,当前示例为:
[submodule "didi"]
path = didi
url = ../didi
当其他人克隆父仓库的时候,将依据此文件中每个子模块的url 拉取数据
可以用【子模块url 修改】
-
子模块是否创建的依据,可以通过在子模块目录查看git log
,成功则显示子模块 的日志
-
git status
默认看不到子模块的信息,需要参考【配置】
-
提示信息中会出现 update
、左箭头<
等相关的字样
遇到问题
操作失败
Q:在分支A 进行了某个操作,同步到分支B 的时候,没有生效
A:
master 分支有didi 子目录,而dev 有didi 子模块 (且是从原先的didi 子目录转化过来)
同时didi 子目录中有一文件temp 是 gitignore 掉的
以如上场景执行merge
操作为例:
(master)$ rm -r temp
(master)$ master merge didi
忽略文件无效
A:在子模块中的文件,并不会被父仓库的.gitignore
文件作用。
Q:需要自己再补充一个,否则可能造成"操作失败"的问题
未涉及部分
子模块引用修改
额,用了git 几年了,基本没有引用修改的情况(都是宁可用新地址重新下一个哈哈哈)
暂时不测试了。(有需要看原文“合并子模块修改 Merging Submodule Changes“小节哦)
嵌套子模块
因为暂时还不在需求范围之内,不做具体使用测试。估计没啥毛病
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)