git submodule add报错的正确处理方式及相关疑问
这是一种能暂时绕过报错的做法,但绝对不是符合Git子模块设计逻辑的正确方案。
先搞清楚报错的原因:当你执行git submodule add时,Git的预期是把一个已有完整版本控制的独立仓库(不管是远程还是本地)关联为子模块。如果待添加的目录本身是本地Git仓库,但处于以下状态,就会触发“does not have a commit checked out”错误:
- 刚初始化仓库,还没做过任何提交
- 处于游离HEAD状态(比如直接checkout了某个commit哈希,而不是分支)
- 仓库没有关联远程,且Git找不到有效的提交引用
为什么删除.git目录能解决报错?
删掉待添加目录里的.git文件夹,等于把这个目录从独立Git仓库打回成普通本地目录。这时git submodule add会把它当成全新的内容,在父仓库里重新初始化一个子模块仓库——但本质是把原目录的文件直接纳入新子模块,原有的版本历史全丢了。
这会不会违背子模块的初衷?
完全会。Git子模块的核心目的是让父仓库引用一个独立维护的仓库的特定提交,两个仓库各自保留版本历史,子模块的更新可以独立进行,父仓库只需要记录它的commit哈希即可。
而删除.git目录后,原目录的版本记录直接被丢弃,相当于把它变成了父仓库管控下的“伪子模块”,完全失去了“引用独立仓库”的意义,和直接在父仓库里加个普通目录没区别,只是套了子模块的壳。
你的质疑有没有错?
你的质疑完全正确。那些建议删.git目录的方案,本质是用丢弃版本历史的代价绕开错误,根本没解决问题的根源——没有按照子模块的正确流程操作。
正确的解决方法
根据你的实际需求来选择:
如果这个目录本来就是你要作为独立仓库的子模块:
- 进入该目录,先确保有至少一次提交:
git add . && git commit -m "初始化提交" - 如果是本地仓库,要么给它关联远程仓库(
git remote add origin <远程地址>后推送到远程),要么直接用本地路径作为子模块源 - 如果处于游离HEAD状态,先切换到分支:
git checkout main(或你的分支名),确保有明确的分支引用 - 回到父仓库,正常执行
git submodule add <仓库地址/本地路径> <子模块存放路径>
- 进入该目录,先确保有至少一次提交:
如果这个目录本来就不需要作为独立仓库:那你根本不需要用
git submodule add,直接把目录复制到父仓库里,执行git add和git commit就行——子模块是用来关联独立仓库的,不是加普通子目录的工具。
内容的提问来源于stack exchange,提问作者whdaffer

