Git 子模块:无法将子模块更新到较早的版本

Git Submodule : Cannot update submodule to an earlier revision

我花了很多时间阅读和试用 git 子模块。但是我真的放弃了。

我的问题:

我正在克隆一个 git 存储库作为子模块。所以,我

git submodule add -b master url localpath

存储库开始下载,并在 .gitmodules 文件中创建相应的条目。 git 子模块状态显示最新提交。

到目前为止一切顺利。

开发过程中,发现子模块中的HEAD commit存在bug。因此,应该将提交从 master 更改为某个提交 ID。

因此,我更改了 .gitmodule 文件中的提交 ID ( 7 aplhanumeric ) from branch = master

branch = <commitid> -> .gitmodule file

也做了

git submodule update --remote

错误是

严重:需要一次修改

无法在子模块路径中找到当前来源/修订

我也试过了

 git submodule foreach git pull

这样它将拉取提交 ID,但它只是 returns 和

正在输入name_of_the_submodule

已经是最新的了。

谁能帮帮我?

P.S: 我已经看过很多教程和问答了。所以如果你想对此投反对票是为了好玩,那么请先指出一个答案,我会删除这个 post.

按照问题中的描述克隆子模块后:

git submodule add -b master url localpath

那么你应该可以changedir到子模块:

cd localpath

进入子模块后,您可以使用任何 git 命令,它们只会影响子模块的 repo。例如,您可以检查那个神圣的分支或修订:

git checkout <branch|tag|hash>

或者检查 master 分支中的倒数第二个修订版:

git checkout HEAD~1

然后 changedir 回到主 git 仓库:

cd ..

并且 git status 应该产生如下内容:

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   .gitmodules
    new file:   localpath

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   localpath (new commits)

然后只需将 changes 添加到您的子模块:

git add localpath

并提交

git commit -m "Add submodule url to localpath with older working commit"

我正在回答我自己的问题,经过一些研究,这可能对其他人有帮助:

理解git子模块是一件很痛苦的事情,但是一旦你理解了,一切就都变得有意义了!

以下post显示:

  • 添加子模块并让其他人与您的子模块同步。
  • 更新子模块并让其他人与您的子模块同步。
  • 删除子模块并让其他子模块与您的子模块同步。
  • 正在更新删除的子模块。

添加子模块

git 子模块添加 -b

.gitmodules(name,path,url,branch)中的条目通过

下载相应的子模块
git submodule update --init

这做了三件重要的事情,其中​​前两件对用户是隐藏的:

  1. 更新 .git/config 有一个额外的条目(子模块)

  2. 在 .git/modules 下以裸格式下载存储库。这意味着,在 .git.

  3. 中有 .git
  4. 从 .git/modules 检出 git 子模块到父目录。

现在,在第 2 天,提交子模块的提交者意识到,他应该将子模块更改为其他提交而不是 HEAD。因此,他会转到他的本地存储库,然后转到子模块路径,然后通过简单地调用

来检查他想要的提交
git checkout <hash>
cd <parent dir>
git submodule status

此时,git 子模块状态仍然没有显示新的哈希值。新的散列仅在更改上演时可见。现在,提交者只需要暂存(添加)、提交和推送更改,以便所有其他开发人员都可以看到。

更新添加的子模块

在第 3 天,其他开发人员只需调用命令就可以更新他们的存储库

git pull # this is to get the latest commit of the parent git repository.
git submodule update --force # update the submodule with latest hash

基本上,这里的要点很简单:子模块直到并且除非被告知这样做才会做出反应。只是做 git pull,不会更新 git 子模块。开发人员可以继续处理他们的本地子模块,而不是将它们同步到服务器上的子模块 "forever"。子模块更新将在显式调用 git 子模块更新命令时发生。

正在删除子模块

现在,在第 4 天,提交者决定完全删除 git 子模块。这里的步骤也不简单,因为没有什么叫做git submodule rm 本来应该等同于git submodule add。这只能且仅当遵循以下顺序时才能完成:

git submodule deinit submodulename
  1. 这将删除 .git/config 条目。

  2. 这会清除子模块目录!!执行此命令后,您将在 submdoule 目录中看不到任何内容。

  3. 但是子模块的内容在.git/modules

  4. 下仍然可用

因此 git status -u 仍然会显示 Everyting 是最新的!

所以显示删除,

git rm submodulepath

此时git状态会return表示.gitmodules已被更改(子模块已被删除),子模块路径已被删除。提交并推送更改。

正在更新删除的子模块

在第 5 天,开发人员想要像 git 子模块更新那样删除子模块 "automatically"。所以他们首先做一个 git pull,它成功地删除了 git 子模块

的所有索引
 git submodule status # shows nothing

但是,.git/config 仍然包含有效的子模块条目,子模块文件夹及其所有内容和裸存储库都在 .git/submodules 下!没有删除它们的命令。所有这些都必须通过手动明确删除..(如果我错了请纠正我)