git 之 submodule

发布于 2021-03-31 10:45:41

[TOC]

0x00 使用说明

git 子模块的一些快速上手技巧

0x01 添加子模块

1. 创建子模块

前提:本地已经有一个主项目,但是没有子模块。

命令:git submodule add <submodule_url>

注意请用 https 开头的连接,而不是 git 开头的

$ git submodule add https://github.com/xxx/project-sub.git project-sub

添加子模块,然后运行git status,

可以看到目录有增加2个文件

  • .gitmodules,这个文件用来保存子模块的信息。
  • project-sub,这个就是你所创建的子模块的文件夹
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   .gitmodules
    new file:   project-sub
# 根目录下的文件:.gitmodules
[submodule "project-sub"]
    path = project-sub
    url = https://github.com/xxx/project-sub.git

如果此前项目中已经存在 .gitmodules 文件,则会在文件内容中多出上述三行记录。

这时候,建议先提交一次 commit

2. 查看子模块

$ git submodule
 e33f854d3f51f5ebd771a68da05ad0371a3c0570 project-sub (heads/master)

3. 主项目克隆到本地

还有一种情况是,带有子模块的主项目需要从仓库中拉取

$ git clone https://github.com/xxx/project-main.git

在主项目文件夹中,有 project-sub 该文件夹

但是里面是空的

# 子模块前面有一个`-`,说明子模块文件还未检入(空文件夹)。
$ git submodule
 -e33f854d3f51f5ebd771a68da05ad0371a3c0570 assets
 
$ ls project-sub
$

这个时候,需要执行两个:init + update

# 进入到 project-sub 同级目录
$ git submodule init
$ git submodule update

另外一种不用手动更新子模块的方式(不适合分支子模块)

$ git clone https://github.com/xxx/project-main.git --recurse-submodules

0x02 更新子模块

使用查看命令来观察项目变动是一个好习惯

$ git status

# 查看版本异同
$ git diff
$ git diff --submodule

1. 子模块有改动,未提交

开发环境居多,直接在项目中更改代码,但是没有递交到远程仓库

  1. 进入子文件夹,提交更新
  2. 到项目中,提交子仓库更新

有一种情况,你忘了子模块推送,直接把主项目推送了,造成了版本紊乱,悔之晚矣。这时候需要 git 来校验我们是否将子模块推送了

$ git push --recurse-submodules=check

2. 子模块远程有更新

负责子模块开发的人做了一些版本升级工作

  • 方式一:进入到子文件夹,同步远程仓库

    # 进入到子文件夹,像同步远程仓库一样操作
    $ cd project-sub
    
    # 拉取仓库方式1
    $ git fetch
    $ git merge origin/master
    
    # 拉取仓库方式2 (建议)
    $ git pull --rebase
  • 方式二:在主项目中进行更新,默认是 master 分支,更改分支改动在 .gitmodules 或者 .git/config 文件中

    $ git submodule update --remote
    
    # 更改分支
    $ git config -f .gitmodules submodule.project-sub.branch <branch_name>

在这个时候呢,还有一种情况,远程仓库有了版本升级,要同步远程仓库

# 在主项目中执行拉取操作,不会同步更新子模块
$ git pull

# 同步远程主项目和子模块
$ git pull --recurse-submodules

3. 子模块 url 有了自己的想法

有一种情况,子模块变更了托管的平台。此时,若父级项目引用的子模块提交不在仓库中本地配置的子模块远端上,那么执行 git pull --recurse-submodulesgit submodule update 就会失败。

在你写 ci 的时候,需要极其注意这个东西。因为好的 ci,只需要写一遍就够了。

# 将新的 URL 复制到本地配置中
$ git submodule sync --recursive
# 从新 URL 更新子模块
$ git submodule update --init --recursive

4. 有趣的 foreach

当你有多个子模块的时候,想要对所有子模块执行相同的操作,比如更新子模块远程仓库,需要一个一个修改过去特别麻瓜。

这个时候就需要使用下面这个命令

git submodule foreach 'git pull origin master'

0x03 删除子模块

1. 方式一:自动删除(建议)

# 在子模块同级目录下面
$ git submodule deinit project-sub

# 连同子模块工作区的工作一块删除
$ git submodule deinit project-sub --force

上面的命令执行的工作流程等同于下面方式二

2. 方式二:手动删除

  1. 删除子模块文件夹

    $ git rm --cached project-sub
    $ rm -rf project-sub
  2. 删除 .gitmodules 文件中相关子模块信息

    [submodule "project-sub"]
      path = assets
      url = https://github.com/xxx/project-sub.git 
  3. 删除 .git/config 中的相关子模块信息

    [submodule "project-sub"]
      url = https://github.com/xxx/project-sub.git 
  4. 删除 .git 文件夹中的相关子模块文件

    $ rm -rf .git/modules/project-sub

0x04 参考资料

0 条评论

发布
问题