Table of Contents

Git Submodule

子模块,也是一个Repository


添加子模块

在主Repository添加

git submodule add <remote repository> <local path>
git submodule add https://github.com/KennyChenFight/git-sub-module.git reference/git-sub-module

添加之后,在主Repository中就会多一个记录子模块信息的文件:**.gitmodules**,内容大概是:

[submodule "reference/git-sub-module"]
    path = reference/git-sub-module
    url = https://github.com/KennyChenFight/git-sub-module.git

在.git文件中也会多出相关的记录内容。

子模块在Github上会显示为一个文件夹+@+一个哈希值的形式,哈希值代表的就是使用的子模块的提交版本,点击跳转。

更新子模块

子模块更新后,需要更新到自己的库:

git submodule update --remote --merge

注意,上面的命令只将子模块的变动更新到了本地,使用以下的命令将本地子模块的更新推送到主Repository的远程:

git add .
git commit -m "update submodule"
git push

自己的理解

通过远端的两个Repository,并不能直接更新子模块,必须经过本地。将本地子模块的更新推送到主Repository的远程后(上面一个步骤),另一个贡献者的本地下一次正常的pull会“更新子模块”(从主Repository拉取来的内容),因为更新过后的子模块也是主Repository的一部分,受正常pull/push的影响。正常情况下,子模块远程的更新是不受正常pull/push的影响的(不能因为我使用的库的作者更新了库,我pull的时候也让我更新)。这里说的更新是从子模块的远端将变动同步到本地,而主Repository远端的子模块有更新(被其他贡献者更新了),使用正常的pull即可同步回来,这里说的子模块更新并不是这种情况。

如果主Repository和子Repository都可能被更新过,可以使用以下命令,把变动同时都拉取回来:(有点乱,不建议用)

git pull --recurse-submodules <branch>

直接在主Repository下修改子模块,然后将更新推送到子模块的远程也是可以的,但是感觉没什么意义,这里不写了。

初始化子模块

git clone <remote_url>
git submodule update --init --recursive

或者

git clone --recurse-submodules <remote_url>

删除子模块并解除关系

# 在主模組目錄下解除submodule關係
git submodule deinit reference/git-sub-module
刪除在.gitmodules檔案的與git-sub-module的內容
git add .gitmodules
git rm --cached reference/git-sub-module
# 這個路徑下的所有檔案刪除
rm -rf .git/modules/reference/git-sub-module 
git commit -m 'remove submodule'
rm -rf reference/git-sub-module
git push

配置

Git Submodule的配置记录在两个文件里面

Q:那么submodule使用的commit id是记录在哪里的呢?