9.1 克隆包含子模块的 Git 仓库
当你克隆使用子模块的仓库时,需要初始化并更新这些子模块。
$ git clone --recursive <url id="cumojpmf2kq15kc4oe7g" type="url" status="parsed" title="Build software better, together" wc="719">https://github.com/username/repo.git</url>
这将克隆引用的子模块,并将它们放置在适当的文件夹中(包括子模块内的子模块)。这等同于在克隆完成后立即运行 git submodule update --init --recursive。
9.2 更新子模块
子模块引用另一个仓库中的特定提交。要检出所有子模块引用的确切状态,运行:
git submodule update --recursive
有时,你可能不希望使用引用的状态,而是想将本地检出更新到该子模块在远程的最新状态。要使用单个命令将所有子模块检出到远程的最新状态,可以使用:
git submodule foreach git pull <remote> <branch>
或者使用默认的 git pull 参数:
git submodule foreach git pull
请注意,这只会更新你的本地工作副本。运行 git status 会列出子模块目录,因为此命令导致了更改。要更新你的仓库以引用新的状态,你需要提交更改:
git add <submodule_directory>
git commit
在使用 git pull 时,可能会有一些更改会导致合并冲突,因此你可以使用 git pull --rebase 将你的更改回滚到顶部,大多数情况下可以减少冲突的可能性。它还会将所有分支拉取到本地。
git submodule foreach git pull --rebase
要检出特定子模块的最新状态,可以使用:
git submodule update --remote <submodule_directory>
9.3 添加子模块
你可以将另一个 Git 仓库作为文件夹包含在你的项目中,并由 Git 进行跟踪:
$ git submodule add <url id="cumojpmf2kq15kc4oe80" type="url" status="parsed" title="GitHub - jquery/jquery: jQuery JavaScript Library" wc="14274">https://github.com/jquery/jquery.git</url>
你应该添加并提交新的 .gitmodules 文件;这告诉 Git 在运行 git submodule update 时应该克隆哪些子模块。
9.4 设置子模块跟踪分支
子模块始终在特定的提交哈希(“gitlink”,父仓库索引中的特殊条目)处检出。
但你可以请求更新该子模块,以跟踪子模块远程仓库中的最新提交。
而不是进入每个子模块,执行 git checkout abranch --track origin/abranch,git pull,你可以简单地从父仓库执行以下操作:
git submodule update --remote --recursive
由于子模块的 SHA1 会更改,你仍然需要跟上:
git add .
git commit -m "update submodules"
这假设子模块是:
- 添加时带有要跟踪的分支:
git submodule -b abranch -- /url/of/submodule/repo
- 或者配置(对于现有子模块)以跟踪分支:
cd /path/to/parent/repo
git config -f .gitmodules submodule.asubmodule.branch abranch
9.5 移动子模块
版本 > 1.8
运行:
$ git mv /path/to/module new/path/to/module
版本 ≤ 1.8
- 编辑
.gitmodules文件,适当更改子模块的路径,并使用git add .gitmodules将其放入索引中。 - 如果需要,创建新位置的子模块的父目录(
mkdir -p /path/to)。 - 将所有内容从旧目录移动到新目录(
mv -vi /path/to/module new/path/to/submodule)。 - 确保 Git 跟踪此目录(
git add /path/to)。 - 使用
git rm --cached /path/to/module删除旧目录。 - 将
.git/modules//path/to/module目录及其所有内容移动到.git/modules//path/to/module。 - 编辑
.git/modules//path/to/config文件,确保worktree项指向新位置,例如worktree = ../../../../..//path/to/module。通常这里应该有两个更多的..。 编辑/path/to/module/.git文件,确保路径指向主项目.git文件夹中的正确新位置,例如gitdir: ../../../.git/modules//path/to/module。 - 最后,提交更改。
此示例来自 Stack Overflow,作者为 Axel Beckert。
git status 输出如下:
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: .gitmodules
# renamed: old/path/to/submodule -> new/path/to/submodule
#
9.6 删除子模块
版本 > 1.8
你可以通过以下命令删除子模块(例如 the_submodule):
$ git submodule deinit the_submodule
$ git rm the_submodule
git submodule deinit the_submodule删除.git/config中的the_submodule条目。这会将the_submodule从git submodule update、git submodule sync和git submodule foreach调用中排除,并删除其本地内容(源)。此外,这不会在你的父仓库中显示为更改。git rm the_submodule会从工作树中删除子模块。子模块的条目也会从.gitmodules文件中删除(源)。如果仅运行git rm the_submodule(没有先运行git submodule deinit the_submodule),子模块的条目将保留在.git/config文件中。
版本 < 1.8
- 从
.gitmodules文件中删除相关部分。 - 将
.gitmodules的更改放入暂存区git add .gitmodules。 - 从
.git/config中删除相关部分。 - 运行
git rm --cached path_to_submodule(路径末尾不要加斜杠)。 - 运行
rm -rf .git/modules/path_to_submodule。 - 提交更改
git commit -m "Removed submodule <name>"。 - 删除现在未跟踪的子模块文件。
rm -rf path_to_submodule