克隆和子模块更新后,Git子模块处于"分离头"状态

Bar*_*man 32 git

当我克隆我的git repo时,其中一个子模块位于一个带有奇怪名称的分支中,我认为这意味着它有一个" 分离头 "(我甚至不确定这意味着什么).

如果我检查我的主分支的子模块,然后运行" git submodule update --init --recursive"它再次发生.

有人知道发生了什么吗?

Von*_*onC 38

子模块总是作为分离的HEAD检出(参见" 为什么git会分离我的头? "),因为父repo的索引只包含SHA1作为索引中特殊条目 ,正如Gary Fixler回答所解释的那样..

即使您将子模块配置为遵循分支(或将现有子模块转换为跟随分支),a git submodule update --remote也会检出该远程分支的最新SHA1,但结果仍然是分离的HEAD.

如果你想为所述子模块做贡献(在其中进行新的提交),你需要进入该子模块并在那里自己创建一个分支.

cd mySubmodule
git checkout -b aNewBranch
# work
git add .
git commit -m "new commits"
git push -u origin aNewBranch

# record the new submodule state in the parent repo:
cd ..
git add mySubmodule
git commit -m "new state of mySubmodule"
git push
Run Code Online (Sandbox Code Playgroud)

Git 2.16(2018年第一季度)的注释:" --merge"可能会覆盖和回退恰好在子模块存储库中检出的分支的历史记录,这可能是不可取的.在这种情况下,
分离--rebase但仍允许递归检出成功.

请参阅提交57f22bf(2017年7月28日),并由Stefan Beller()提交3ef2538(2017年7月24日).(由Junio C Hamano合并- -提交0b75572,2017年12月6日)git submodule update --remote (--merge/--rebase)
master

递归子模块:从新状态分离HEAD

当子模块位于分支上并且在其超级项目中运行递归检出时,子模块的分支将更新为超级项目检出的内容.
这在Git的当前模型中是非常出乎意料的,例如' git submodule update --remote (--merge/--rebase)'总是分离子模块HEAD.

尽管计划在未来将子模块HEADS分离,但当前的行为非常糟糕,因为它与用户期望不匹配,并且不检查是否丢失了提交(仅通过reflog恢复).

更新时,在子模块中无条件地分离HEAD.

  • @Thomas它是上游分支(http://stackoverflow.com/a/4879224/6309):另请参阅http://stackoverflow.com/a/17096880/6309. (3认同)

Gar*_*ler 16

git目录的内容存储在名为"trees"的简单文本文件清单(即目录列表)中,如下所示,其中blob是文件的内容,而树木更像是这样的树:

100644 blob 0c31be662540ce902cee106f86bfdeef519fc662    .gitignore
100644 blob 1d364edf530c2238e79162bf2d9f30c2af610347    .gitmodules
040000 tree fc6bc39202ec20228e9135cd426110c558b625cd    foo
040000 tree 2f9fc460f3a2370ed45b39b2bcaaf9b6e746b823    bar
Run Code Online (Sandbox Code Playgroud)

但是,如果bar是一个子模块,而不仅仅是一个目录,那么包含它的树将如下所示:

100644 blob 0c31be662540ce902cee106f86bfdeef519fc662    .gitignore
100644 blob 1d364edf530c2238e79162bf2d9f30c2af610347    .gitmodules
040000 tree fc6bc39202ec20228e9135cd426110c558b625cd    foo
040000 commit 2f9fc460f3a2370ed45b39b2bcaaf9b6e746b823  bar
Run Code Online (Sandbox Code Playgroud)

请注意,它不是bar,而是树,它现在是一个提交(在子模块中).这是关于树/提交级别的子模块的所有git存储,因此它无法知道提交所在的分支.实际上,存储分支名称是行不通的.他们可以改变.另外,如果您检查回购中需要回滚子模块的旧提交,那么分支是否应该移回子模块中?这会将新分支位置之后的提交转换为未引用的区域.

分支是供人类使用,以理解DAG,以及特定的思路.Git并不关心我们如何引用提交.它需要一个具体的位置,以便您可以安全地移动包含的repo,并且知道子模块将始终检出它当时的位置.唯一的事实是哈希.