此线程的 (Easy way to pull latest of all git submodules) 回答指出运行时:
$ git pull --recurse-submodules
将拉取子模块中的最新提交。但是试了一下,好像不行。
我有一个演示存储库,其中包含一个名为“tinyXml”的演示子模块(这不是真正的 tinyXml,只是一个演示)。看看下面的shell交互:
PS D:\DemoProject> cd .\tinyXml
PS D:\DemoProject\tinyXml> git status
HEAD detached at 9101c63
nothing to commit, working tree clean
PS D:\DemoProject\tinyXml> cd ..
PS D:\DemoProject> git pull --recurse-submodules
Fetching submodule tinyXml
Already up to date.
PS D:\DemoProject> cd .\tinyXml\
PS D:\DemoProject\tinyXml> git status
HEAD detached at 9101c63
nothing to commit, working tree clean
PS D:\DemoProject\tinyXml> cd ..
PS D:\DemoProject> git submodule update --remote
Submodule path 'tinyXml': checked out 'e249788ed10afbdff043f758f46add75b81d522a'
所以您看到 git submodule update --remote
有效,但 git pull --recurse-submodules
没有提取子模块中的最新提交。
我的 git 版本 - 2.32.0
答案 0 :(得分:0)
正如您从日志中看到的,您的一些子模块不在分支上,而是处于分离状态。
您应该进入每个子模块并检查正确的分支,然后返回并再次发出 public function courseDelete($courseId)
{
dd($courseId);
}
命令。
答案 1 :(得分:0)
简短的回答是否定的。那是因为子模块不应该使用最新的提交。
子模块的意图是 superproject 存储库指定要在子模块中使用的提交。超级项目存储库没有列出子模块中要使用的分支名称;这不可靠。因此,超级项目存储库会列出要在子模块中使用的原始哈希 ID,因为它可靠。
子模块因此被检出为“分离的 HEAD”。这是设计使然。
请记住,每个子模块都是一个单独的 Git 存储库。它不是超级项目的一部分。超级项目存储库只列出用于克隆子模块的 URL,以便 Git 可以运行 git clone
,加上路径(以便超级项目知道在哪里放置子模块)和正确的哈希 ID(以便超级项目知道将哪个提交用作分离的 HEAD)。
现在,有一种方法,可以从超级项目存储库中请求超级项目 Git 在子模块中做一些不同的事情。这种方式不能运行git pull
。相反,您需要带有特定标志的 git submodule update
。您想要的特定标志包括但不一定限于 --remote
。
我上面说过,超级项目没有为每个子模块列出一个分支。这只是部分正确。超级项目可以为每个子模块列出一个分支名称。但请记住这一点:分支名称只是一种表示“获得某些特定提交”的方式。哪个特定的提交是?嗯,这是棘手的部分,因为每个 Git 存储库都有自己的分支名称。您的超级项目 Git 有自己的分支名称,您克隆的每个子模块都有其自己的分支名称,每个存储库从中克隆的存储库都有自己的分支姓名等。
这很令人困惑,因为此时这里涉及的 Git 存储库绝对最少四个:
origin
,您可以从中获得提交。git clone
创建的。origin
,it 从中获得提交。当您克隆某个 Git 存储库时,您会获得他们的所有提交,而没有他们的分支。然后您的 Git 在您自己的本地存储库中创建一个分支。您的 Git 获取它们的分支名称并更改,将它们转换为您自己的 Git 的远程跟踪名称:它们的 main
或 {例如,{1}} 成为您的 master
或 origin/main
。
对于您的每个子模块也是如此。当您的超级项目 Git 运行 origin/master
来克隆一些 other 存储库作为 git clone url path/to/submodule
中的子模块时,那个 submodule Git此 path/to/submodule
命令复制的存储库......好吧,这就像任何其他 git clone
一样。 Git 会从该 URL 复制他们的所有提交,而没有复制任何分支。所以 branch 名称在这里实际上没有用。您的超级项目存储库 R 允许(但不是必需)为子模块 S 存储的“分支名称”根本不是您的 分支名称— 因为那没有用 — 而是 S 的 git clone
中的分支名称 。
您的超级项目 Git 将在 R 中运行,实际上:
origin
这将使您的 Git-that-controls-S 使用 (cd path/to/S; git fetch)
从 S 的 git fetch
获取提交。这将更新 S 的远程跟踪名称,例如 S 的 origin
和 origin/main
等
如果 R 说 S 应该使用“分支功能”,这实际上意味着在 R 中运行的 Git 应该运行:
origin/feature
紧随其后:
(cd path/to/S; git fetch)
在 S 中运行的这个 (cd path/to/S; git rev-parse origin/feature)
将获得在 S 中找到的 git rev-parse
的提交哈希 ID,它刚刚由 { {1}} 您的 Git 在 S 中运行,以获取原始哈希 ID。
这就是origin/feature
中的git fetch
的意思:在子模块中运行--remote
后,使用存储在R中的分支名称来构造远程-将在 S 中找到的跟踪名称,以获取提交哈希 ID,以便在 S 中查找。
git submodule update --remote
命令的 rest 决定了用这个哈希 ID 做什么。使用 git fetch
,处理这个哈希 ID 的操作是使用该哈希 ID 的分离 HEAD 的 git submodule update
。
因此:
--checkout
将进入您的存储库 R 的每个子模块 S 并运行 git checkout
和 git submodule update --recurse --checkout --remote
并执行分离的 HEAD 检出 S 视情况 和 将在 S 内部递归以更新 S 具有的任何子模块。>
不过,您可能不想要 git fetch
。您做什么要取决于太多因素,无法真正进入这里。我要注意的一件事是,一旦子模块处于您希望它们进行的提交上,您需要进行新的 superproject 提交以记录这些哈希 ID超级项目。这也可能很痛苦。
是的,是的。我无法回答“为什么”,只能说明这从根本上来说是一个难题。
现在可能有人正在做这件事。有一些项目正在进行中以改进子模块。这……很难。
这就是今天的情况。不要使用git rev-parse
;这不适合工作。即便是 --checkout
也可能无法胜任你的工作,无论那是什么。