GIT submodules

By | 7月 17, 2026

简介

submodule 用于在一个 git repo 中包含其它 git repo,内部的 git repo 被称为 submodule。submodule 的实现原理:

主仓库并不保存子仓库代码
↓
只保存子仓库的 commit SHA
↓
checkout 时再去子仓库仓库取对应 commit

因为它记录的是子仓库的 commit SHA,缺乏明确的版本管理,所以 submodule 并不是解决项目依赖的推荐方法。

{parent_repo}/.gitmodules

它告诉主仓库

  • submodule 在哪里
  • 从哪个 URL 拉取
  • (可选) 使用那个 branch
[submodule "libs/lib"]
    path = libs/lib
    url = https://github.com/example/lib.git
    branch = main

子仓库的 commit SHA 记录在主仓库的 git tree 里

添加或修改子仓库后,在主仓库 commit,其实就是在保存当前子仓库对应的 commit SHA。

查看 submodule commit SHA 的命令:git submodule status

$ git submodule status
  3de8cf12908c4d0a55b0a0c309969e2514ab0532 submodules/blog (heads/main)

新添加的 submodule 是最新的 commit SHA,随着开发,通常需要依赖子仓库的某个 release (tag,例如 release/v1.2)。更新子仓库 commit SHA:

  1. 子仓库:
    • git fetch –tags
    • git checkout release/v1.2
  2. 主仓库:
    • git add libs/lib
    • git commit -m “Upgrade lib to v1.3.0”

主仓库的 commit 记录

git ls-tree HEAD

输出可能类似:

100644 blob     abc123...    .gitmodules
040000 tree     def456...    src
160000 commit   7f8e9d...    libs/lib

160000 commit 7f8e9d... libs/lib 记录着 submodule 的 commit SHA。

  • 160000 = Git 特殊文件类型,表示 submodule
  • 7f8e9d... = submodule 对应的 commit SHA
  • libs/lib = submodule 路径

常用命令

添加 submodule

git submodule add https://github.com//rock rock

下载 submodule

普通 git clone 主仓库,不会 pull submodules 的内容。

添加 –cursive 在 git clone 时拉取所有内容。

git clone --recursive <project url>

或者在主仓库里,手动更新所有 submodules。

git submodule update --init --recursive

抽取 folder 为 独立 repo,并保留 commit history

比如 main-repo 里有 gui, server, tools 等 folder,如果想把 tools folder 独立成一个 git repo,并且保留 commit history。这样抽取出来的 tools repo 就可以共享给其它 project 了。

执行下面的命令后,当前 folder 就只包含 tools 里的内容,可以把它 push 到仓库里了。

git clone {main-repo-url}
cd main-repo
git filter-branch --subdirectory-filter tools -- --all
git remote set-url origin {tools-repo-url}
git push

总结

  • 在选择 git submodule 时,想想有没有其它更好的方案。很多语言都有自己的 lib 管理工具,例如 Java maven,Node npm,Python pip 等。
  • 不适合在主仓库里对子仓库修改,然后 push 回子仓库
  • submodule 的 commit SHA 更新后,其它人需要手动更新一下 git submodule update