0%

git submodule 的使用

前言

大概整理下 git submodule 的用法。

使用场景

在一个项目中,需要使用其它项目,或者想把一些模块抽离出来成为公共模块。除了使用 pod 以外,还可以使用 git submodule 来达成目的。本次主要介绍 sourcetree 里如何进行操作。

基础用法

现有两个项目 submodule-demo 和 module-1, 想在 demo 里使用 module-1。

  1. clone demo
  2. Repository -> Add submodule, Source Path/URL 中填入 demo 的仓库地址,Local Relative Path 选择本地 demo 目录下的 module-1 文件夹,然后点击 OK . 生成文件 .gitmodules 和 subproject module-1
  3. git commit & git push

克隆一个带 submodule 的项目

  1. clone demo, 有 module-1 文件夹但是是空的
  2. sourcetree 左侧 submodules , 双击 module-1,进行拉取。命令行操作为 git submodule init 初始化本地配置文件, git submodule update 更新 submodule
  3. 如果 module-1 仓库有更新,双击 module-1,进行更新,HEAD 指向的即为 demo 所依赖的 module-1 版本。可以在本地 module-1仓库里进行 git chekout 指定 branch 或者 commit。

注意

如果其它人在 demo 里的 module-1 进行了变更,但是并没有提交到远程的 module-1仓库,然后又把 demo push,就会把指向本地 module-1 的引用也提交到了远端。此时另外的人在 demo 里进行 git submodule update 时就会报错,找不到当时的引用。

1
2
error: Server does not allow request for unadvertised object 857a1126d7a1ad9f91449602f6bb09f8130b2a1d
Fetched in submodule path 'module-1', but it did not contain 857a1126d7a1ad9f91449602f6bb09f8130b2a1d. Direct fetching of that commit failed.

此时可以在 demo 下 git log -l module-1 查看 module-1 提交日志找到该人员将 demo 下的 module-1 提交。如果废弃上次提交的话可以重新 checkout 指定 module-1。

优缺点

优点是可以使依赖关系简单明了,但是同样也会有缺点。每次在 demo 里执行 git submodule update 的时候,会获得一个分离的 HEAD 指向提交,容易丢失。例如在 demo 下执行 git submodule update 以后,在 module-1 里不创建分支直接进行提交,如果此时再在 demo 下执行 git submodule update 就会毫无提示的覆盖掉上次的提交。想要找到丢失的提交可以使用 git reflog . 因此建议在 module-1里新建分支后再进行操作。有两个问题:

  1. 如果在有 module-1 的分支上本地提交,切换回没有 module-1 的分支删除 module-1文件夹,再切换回含有 module-1 的分支,会造成 module-1的 HEAD 混乱,需要重新 checkout。

  2. 如果在切换回没有 module-1 的分支上后,对 module-1 进行了修改,当前分支不会显示任何提交,切换回含有 module-1 的分支也不会显示有任何提交。但是对该分支 push 以后,会造成 git submodule update 的错误。

  3. demo 在新建分支 branch1 上添加 module-1 以后,如果再切换回不带 module-1 的分支,仍然会有一个 module-1 的文件夹。此时要把 module-1 目录删除,当切换回带有 module-1 的分支时要重新 clone。

  4. 最后一个问题是如果想把子目录改为 submodule 的形式,需要以下操作。

    要先把 module-1 备份提交git! 要先把 module-1 备份提交git! 要先把 module-1 备份提交git!

    1
    2
    3
    git rm -r --cached module-1
    rm -rf module-1
    git submodule add module-1.git module-1

参考

https://git-scm.com/book/zh/v1/Git-工具-子模块