如果使用跟踪分支,子模块功能如何在内部实现

马克斯·科列茨基

我正在阅读关于子模块的这篇很棒的文章,它解释了子模块作为一种特殊类型的文件保存在主存储库提交树中:

[/tmp/git/super(master)]$ git ls-files --stage 
100644 831cdc0dc1b88e69aa9943cf09907ae1bcd031fc 0   .gitmodules
160000 85ab8ba4edf9168ab051ded7ddbbe20861b71528 0   ProjectA     <--------
100644 16f5c2d3aa9656fc424352e4cfaa2523c809778b 0   super.txt

哪里85ab8ba4edf9168ab051ded7ddbbe20861b71528是外部/子模块存储库中提交的哈希值。

如果我使用带有跟踪分支的方法:

# add submodule to track master branch
git submodule add -b master [URL to Git repo];

# update your submodule
git submodule update --remote 

它在内部如何运作?

我认为:

  • 跟踪分支设置在子模块克隆存储库中
  • 跟踪分支被添加到 .gitmodules

但是引用提交的特殊文件会发生什么?它是否仍然保留来自子模块的提交哈希?

跟踪分支功能是否仅影响我运行时的行为

git submodule update --remote 

因为它检查子模块跟踪分支并检查新提交并更新主存储库的索引?

周二

背景(随意跳到下一节)

关于子模块要记住的主要事情是在子模块加入超级项目的地方总是涉及两个Git。

超级项目至少有三条信息。两个在.gitmodules

  • 完整路径,例如path/to/ProjectA(如果子模块在某些子目录集中)或简单ProjectA(如果子模块位于顶层);
  • URL,以便git clone ...在您克隆超级项目(但不是其子模块)后,Git 可以运行以获取子模块。

指标(如见过git ls-files --stage有两条信息:

  • 完整路径,例如,path/to/projectA(必须与.gitmodules条目匹配);
  • 你想要的提交哈希,例如,85ab8ba4edf9168ab051ded7ddbbe20861b71528

由于这些重叠,你显然会失去同步:如果你改变路径,事情就会变得有点奇怪。

不过,子模块本身是一个 Git 存储库。这意味着除了commits之外,它还有 a HEAD、分支、标签等等。的内容HEAD代表当前提交最初,当超级项目控制一切时,子模块的 Git 会被告知:通过按哈希 ID 检出一个特定提交来分离HEAD,例如,85ab8ba4edf9168ab051ded7ddbbe20861b71528

不过,您可以进入子模块,并查看分支名称或不同的标签。您可以运行git fetch以从该子模块 Git 的usptream获取提交,这与超级项目无关。简而言之,您可以在任何旧的 Git 存储库中执行任何您可以执行的操作。

但是一旦你这样做了,事情HEAD就不同步了:解析到的提交 ID可能与存储在超级项目中的提交 ID 不匹配。

对子模块使用分支名称

git submodule add -b master [URL to Git repo];

...跟踪分支被添加到 .gitmodules

是的。它就在那里,等待您的下一个命令:

git submodule update --remote

它将它从那里(或其他地方1捞出来,并使处理子模块的 Git 运行:

git fetch [potential additional options]

后跟git merge, git rebase, 或 之一git checkout,具体取决于更多标志和选项和设置。传递给下一个命令的参数还取决于更多标志、选项和设置。

一旦完成,子模块本身可能会检出一些其他提交。也就是说,git rev-parse HEAD在子模块中运行,命名除85ab8ba.... 所以现在你的超级项目和子项目不同步:你的超级项目85ab8ba...专门要求提交,但你的子模块没有“开启”那个提交。

现在你的工作是确保超级项目在新的子模块散列就位的情况下正常工作。如果是这样,您可以——在超级项目中——git add在子模块的路径上运行这会更新特殊索引条目,保持路径不变,但将新的提交哈希写入其中。

现在您可以git commit在超级项目中。像往常一样,索引的内容决定了新提交的内容。提交将记录新的哈希 ID。.gitmodules包含分支名称的内容没有改变,所以.gitmodules新提交中.gitmodules记录的版本与旧提交记录的版本相同超级项目中新哈希 ID 的唯一标志是存储在提交中的哈希 ID(将被复制回git checkout超级项目存储库中该提交的索引)是更新后的。


1个在这一点上使用的分支取自.gitmodules 除非有一个submodule.<name>.branch在设置$GIT_DIR/config配置设置会覆盖.gitmodules设置。<name>部分是superproject 中的当前分支名称所有这些不同的东西都需要限定,因为我们同时查看两个 Git:超级项目 Git 存储库和子模块 Git 存储库。

(现有的 Git 文档似乎不太擅长在这里保持明确的区别。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章