git submodule 游离分支(detached)产生原因及解决办法

submodule 是很方便的功能,但在使用中有一些痛点,其中对我们项目困扰最大的就是游离分支了,昨天专门花时间研究了下,终于弄懂了,这里记录下来,希望能帮到大家。

submodule 的原理

在说产生原因之前,先说下其原理,否则不太好说清楚。

  1. 在主仓库里,只记录 submodule 的commit id,相当于一个指向 submodule 的指针(为了描述方便,我们给这个指针起个名字叫sptr)。
  2. 子模块的分支是记录在 .gitmodules 里的,sptr只记commit id, 不记其他任何信息,如果要改子模块分支,可以使用git config -f .gitmodules submodule.xxx.branch master命令。
  3. 在主仓库下执行 git submodule update --remote 等价于进入 submodule 目录内,然后执行 git pull, 这两个操作都会把 submodule 目录中的文件(同样为了描述的方便,我们给它命名为scode)更新到最新,并且更新sptr
  4. 在主仓库执行 git pull 并不会更新scode, 哪怕pull之后sptr已经指向一个新的commit了,只有执行git submodule update, 才会更新scode
  5. 本地sptr产生变动后,把它push到origin, 这时其他人在拉代码时,都会更新sptr, 但scode是否更新,还要看他们是否执行了git submodule update

更详细的描述,请查看:7.11 Git 工具 - 子模块

产生原因

如果了解了以上5点,那产生原因就比较容易说清楚了。

简单来说,就是主仓库的sptr指向一个你本地不存在的commit id时,子模块就会进入游离分支。

举个例子,假如有个子模块 s1, 有100次提交,为了方便,我们假设commit id 就是1~100这样的数字。

本来 sptr 指向100,也没人更新子模块,这时大家都相安无事,直到有一个人更新了子模块,并push了一个commit id=101的提交,并且他还把sptr更新到101并推到了主仓库的远端(origin).

这个时候,别人在主仓库下执行git pull时,sptr就会指向101,但是当git去子模块里找这个commit id时,由于还没执行git submodule update --remote, 根本就找不到101这个提交,然后子模块就会进入detached HEAD 101的状态,也就是进入到了游离分支。

解决办法

知道了原因,再解决起来就很容易了。

只要我们在执行主仓库的git pull时,先执行一下git submodule update --remote, 把子模块更到最新,这样所有的commit id都有了。不管主仓库的sptr指向哪个commit id,我们都可以适应,也就不会进入游离分支了。

以上就是本文的所有内容,希望对大家有所帮助。
END

你可能感兴趣的:(git submodule 游离分支(detached)产生原因及解决办法)