你不知道的Git系列☞Submodule篇

528 阅读3分钟

前言

今天分享一个我平时用的git工具手册,助力开发,喜欢的可以点赞+收藏下 ,本篇主要介绍常见的git配置操作指令(篇幅较长可根据目录直达)

温馨提示

如对git基础概念还是特别熟悉的小伙伴可以浏览下一下相关文章恶补下

1.5 Git Submodule 介绍

Git submodule允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。当进入子模块目录后,你就进入了子模块的本地仓库,在此目录的所有的修改和提交都是在对子模块的Git仓库进行操作。

image.png

1.5.1 新增Git Submodule

# 添加Submodule

$ git submodule add [-b branch] <remote_url> [destination_folder]

执行新增submodule指令时,Git会在执行如下动作:

1、 将目标Git仓库clone到你指定的路径

2、 在当前仓库创建.gitmodules文件,用于保存和管理submodule的远端地址

3、 在当前仓库的.git/config中添加submodule配置

4、 目标submodule和.gitmodules将被添加到暂存区等待提交

此时你可以查看submodule的状态

# 查看Submodule状态

$ git submodule

  使git status命令支持submodule状态显示

# git status展示Submodule状态

$ git config --global status.submoduleSummary true

  使git diff命令支持submodule日志显示

# git status展示Submodule状态

$ git config --global diff.submodule log

  接着,你需要将其提交到Git仓库

# 提交Submodule并推送远端仓库

$ git commit -m "Added the submodule to the project."

git push

1.5.2 拉取和更新Submodule

当clone包含有submodule的项目时,你需要在指令中使用--recurse-submodules参数。这样项目中的子模块才会被拉取到本地,否则你将得到一个空的目录。

# 完整clone包含Submodule的项目

$ git clone --recurse-submodules [url] [--branch branch_name]

  如果clone主项目时未使用--recurse-submodules参数,可以执行如下命令拉取submodule。--recursive参数用于递归对submodule的submodule执行操作。

# 拉取Submodule

$ git submodule update --init --recursive


# 等同于以下命令

$ git submodule init

$ git submodule update --recursive

上面这两种方式拉取的是Git主仓库中保存的submodule仓库的指定提交,当然你也可以拉取submodule仓库的最新提交。使用--merge或--rebase参数将会在更新submodule时执行合并动作,当然你也可以进入submodule目录,按照常规的Git操作进行代码更新和合并。

# 拉取Submodule最新提交

$ git submodule update -–remote [--merge/--rebase]

使用不包含--merge或--rebase参数的submodule update指令拉取或者更新submodule后,submodule仓库处于 “游离的 HEAD”的状态(detached the HEAD)。这意味着没有本地工作分支(例如 “master”)跟踪改动,所以你在submodule中做的任何改动都不会被跟踪。

 

1.5.3 提交submodule

提交submodule首先要确保submodule仓库处于本地工作分支状态。要切换到本地工作分支状态,你可以依次进入所有submodule目录,执行Git切换分支指令。也可以使用遍历submodule的指令foreach来切换分支。

# 遍历切换submodule分支

$ git submodule foreach [--recursive] git checkout [branch_name]

接着修改代码并提交到暂存区,最终推送到远端的submodule仓库。

# foreach遍历推送submodule更新到远端仓库

$ git submodule foreach [--recursive] git push [remote] [branch_name]


# 遍历推送所有submodule更新到远端仓库

$ git push --recurse-submodules = on-demand

最后,需要将新的submodule commit id推送到主仓库(即使你未对submodule代码做修改,只是同步到submodule仓库最新的提交,那么commit id也发生了变化。如果需要使用最新的代码,就需要推送submodule commit id推送到主仓库)。

# 更新主仓库submodule commit id

$ git commit –m "Submodule updated"

$ git push [remote] [branch_name]

 

1.5.4 遍历submodule

Git提供了submodule foreach命令,用于在所有submodule批量执行常规Git操作。

#批量在submodule仓库执行常用Git命令

$ git submodule foreach [--recursive] git push [remote] [branch_name]

 

1.5.5 删除submodule

# 删除submodule 

$ git submodule deinit <submodule>

$ git rm <submodule> 

$ rm -rf .git/modules/<submodule>

 

1.5.6 submodule注意事项

l 在父项目中git pull并不会自动更新子模块,需要调用git submodule update来更新子模块信息。如果忘记调用git submodule update,那么你极有可能再次把旧的子模块依赖信息提交上去。

l 调用git submodule update并不会将子模块切换到任何分支,默认情况下子模块处于“游离的 HEAD”的状态。如果此时我们改动子模块而没有检出一个工作分支,那调用git submodule update时你所做的任何改动都会丢失。

l Git子模块在父项目中维护所有依赖的子模块版本,当包含大量子模块时,父项目的更新将很容发生冲突,并且父项目的维护历史与所有子模块的维护历史相互交织,维护成本也会比较高。

后言

感兴趣的小伙伴可以浏览下以下系列相关文章(欢迎点赞+关注)

文章链接