DEBUG.WIKI
丽萨主机;为跨境业务选好 IP;原生 / 住宅 IP · 按套餐选择;查看 IP →
阿里云;从建站到云上业务;云服务器 · 数据库 · 对象存储;查看产品 →
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Git clone 后子模块目录为空

普通克隆未初始化子模块时,补做 update --init 并检出主项目记录的提交。区分未初始化、提交不匹配和冲突,保留已有修改。

普通 git clone 完成后,主项目文件齐全,某个依赖目录却是空的。继续 git pull 也没有把文件拉下来,而重新递归克隆可以拿到依赖。如果该路径是 Git 子模块,已有仓库通常可以直接补做初始化,不必删除整个工作目录。

主项目记录子模块的位置和应使用的提交,子模块自身仍是独立仓库。拉取主项目并不等于已经把每个子模块检出到本地。下面针对带工作区的普通克隆;下载 ZIP、裸仓库或稀疏检出造成的缺文件,需要另外区分。

确认空目录确实属于子模块

在主项目根目录查看 .gitmodules,核对其中的路径与仓库地址,再运行:

git status --short
git submodule status --recursive

子模块状态中,提交 ID 前的 - 表示尚未初始化;+ 表示已检出的提交与上层仓库索引记录不一致;U 表示存在合并冲突。三种情况不能都按“少下载了文件”处理。

如果路径根本没有列在子模块状态中,先确认当前分支是否包含该依赖,不要对普通目录执行 git submodule add 来补救。add 是把仓库登记成新的子模块,会改变项目配置。

执行后续命令前,保存已有修改,检查需要访问的子模块地址是否可信。私有子模块可能需要单独的访问权限,主项目克隆成功不代表其依赖仓库也可访问。

给现有克隆补齐初始化和检出

以实际子模块路径替换 vendor/library:

git submodule update --init --recursive --checkout -- vendor/library

--init 为尚未初始化的子模块建立本地配置;更新过程克隆缺少的仓库、获取缺少的提交,并更新工作区。--recursive 继续处理其嵌套子模块。显式 --checkout 要求检出上层仓库记录的提交,避免本地更新策略选择合并或变基。

只需要某个依赖时保留路径限制。确定整个项目的子模块都需要获取,且已核对地址和本地修改后,可以去掉最后的路径:

git submodule update --init --recursive --checkout

已有 submodule.active 等限制配置时,应同时检查实际选中的范围。单独执行 git submodule init 主要建立配置,不完成这里所需的文件检出。

不要为了让命令继续执行就加 --force。如果已有子模块存在本地改动,应先在那个子模块中保存工作;如果报认证失败、仓库不存在或指定提交取不到,应按对应错误检查 URL、权限与远端对象,重复初始化不会解决这些错误。

文件出现后核对提交,而不是追到远程最新

完成后再次查看:

git submodule status --recursive
git status --short

目标子模块不应再显示未初始化的 -。出现 + 时,查看是否有意检出了别的版本;出现 U 时先解决冲突。还应按项目自己的构建或测试流程,确认所需依赖文件可用。

使用 checkout 策略后,子模块处于 detached HEAD 是正常结果:它固定在主项目记录的提交上。若准备在子模块中开发,先按团队流程创建或切换工作分支,不要为了消除提示就随意切到远程分支最新提交。

本次补文件也不需要 --remote。那个选项会改为参考子模块的远程跟踪分支,可能带入主项目尚未采用的版本,改变了修复目的。

后续克隆时一起获取

对于已信任且确认要获取全部子模块的项目,可在首次克隆时使用:

git clone --recurse-submodules https://git.example.com/team/project.git

地址是占位值。该选项会在主项目克隆后初始化并获取子模块,效果对应递归的初始化更新。它不代替依赖安装、编译或项目自己的生成步骤。

如果只是想撤销一次尝试,不要直接删除 .git/modules,也不要强制反初始化带修改的子模块。已经下载的对象通常可以保留;需要恢复原工作状态时,依据执行前保存的提交与修改逐项处理。初始化本身不要求向远端推送,也不应产生一份把子模块随意升级后的主项目提交。