git submodule
git将submodule有关的信息保存在两个地方:.gitmodules在仓库中,有版本控制,修改之后会同步到其他仓库,使用submodule相关命令的时候会自动更新.git/config在本地,需要手动更新,或者执行git submodule sync将新的配置从.gitmodules拷贝到.git/configgit submodule sync会将submodule远程的 url 配置设置到.gitmodules,并且只会影响.git/config已经有 url 的条目- 指定
--recursive,将会递归更新注册的submodule
应用场景
- 场景1:添加一个
submodulegit submodule add repo_url local_path- 此命令做三件事:克隆工程到本地;创建/修改
.gitmodules标记submodule的具体信息;更新.git/config文件,增加submodule的地址 - 可用
git submodule add -b branch_name repo_url local_path指定submodule跟踪的分支
- 场景 2:删除一个
submodulegit submodule deinit -f -- path_to_submodule(路径最后不要加斜线)- 删除
.git/modules下面的文件夹 - 从 git 版本控制中删除缓存的子模块对应文件夹
- 本地仍保留文件
git rm --cached path_to_submodule(路径最后不要加斜线) - 本地不保留文件
git rm -f path_to_submodule(路径最后不要加斜线)
- 场景 3:更新
submodule的url- 删除
.git/config相关代码 - 删除工程目录下的
.gitmodules相关代码 - 执行
git submodule sync --recursive更新到本地的配置文件
- 删除
- 场景 4:克隆一个有
submodule的项目- 分步克隆
git clone repo_url,submodule的代码不会和父项目一起克隆出来git submodule update --init [--recursive]可以检出submodule的代码,recursive适用于嵌套submodule的项目git submodule update --init [--recursive] subname可以检出指定子模块subname的代码,recursive适用于嵌套submodule的项目- 一步克隆
git clone repo_url --recursive
场景 5:更新
submodule,与远程仓库同步- 更改对应的
submodule提交到远程仓库 - 在父工程中,进入该
submodule,执行git pull,可以用git status查看submodule是否有改到 - 如果有改到,需要执行
git add提交该submodule的更新 - 也可在父工程中执行
git submodule update --remote更新所有子模块到最新版本,再执行git add提交所有子模块的更新 - 注意:在含有子模块的工程中,每次执行
git pull之后需要执行git submodule update --remote更新子模块 技巧:可以通过修改
~/.gitconfig设置每次git pull之后执行git submodule update --remote[alias] psu = !git pull && git submodule update
- 更改对应的
问题
- 问题 1:
git submodule add时报错A git directory for xxx is found locally with remote(s): origin- 删除
.git/config相关代码 - 删除工程目录下的
.gitmodules相关代码 - 删除缓存的子模块
git rm --cached path_to_submodule`(路径最后不要加斜线) - 执行
git submodule sync --recursive更新到本地的配置文件
- 删除
- 问题 2:
git submodule add时报错Pathspec xxx is in submodule- 删除缓存的子模块
git rm --cached path_to_submodule(路径最后不要加斜线)
- 删除缓存的子模块
高级命令
- 查看差异输出,使得子模块的差异输出更加具体
git diff --cached --submodule - 修改子模块跟踪分支
- 只修改本地:修改
.git/config文件中对应子模块的设置 - 修改仓库:
- 修改
.gitmodule的命令git config -f .gitmodules submodule.Utility.branch devUtility是子模块的名字dev是Utility的分支- 不用
-f .gitmodules只会应用到本地
- 同步到本地配置
git submodule sync????
- 只修改本地:修改
- 在主项目查看子模块的更改摘要:配置选项
status.submodulesummary,使用命令git config status.submodulesummary 1 - 子模块遍历
- 遍历子模块保存工作进度
git submodule foreach 'git stash save' - 遍历子模块新建工作分支
git submodule foreach 'git checkout -b featureA' - 在主项目查看所有子模块的修改内容
git diff; git submodule foreach 'git diff' - 删除所有子模块本地的修改
git submodule foreach --recursive 'git checkout .'
- 遍历子模块保存工作进度
- 在主项目修改子模块
git submodule update更新子模块的文件时,会将子仓库留在一个游离的HEAD状态,本地没有工作分支跟踪改到- 首先进入子模块检出一个分支,修改之后提交到本地
- 拉取远程仓库的子模块提交并合并到本地
git submodule update --remote --rebase/merge
- 发布子模块的改到
- 在主项目推送代码到远程仓库前检查本地有没有未推送的子模块修改
git push --recursive-submodules=check - 如果提交的子模块改到未推送,会导致主项目的推送失败,可以根据提示进入子模块然后推送到远程仓库
- 或者使用
git push --recursive-submodules=on-demand,git会尝试推送子模块修改到远程仓库,只有子模块都推送成功,主项目才可以推送
- 在主项目推送代码到远程仓库前检查本地有没有未推送的子模块修改