git 子模块 deinit 在子模块 url 更改后无法按预期工作

问题描述 投票:0回答:1
git clone --no-checkout myreop
cd myrepo
git checkout branch001
git submodule update --init
# all good
cd ..; mv myrepo myrepo.backup

git clone --no-checkout myrepo
git checkout branch002
git submodule update --init
# all good

即使子模块仓库地址在branch001和branch002之间发生了变化,一切都很好。 我可以预期这会起作用,因为

.git/config
已通过将branch002克隆到中而被删除 一个空目录。但是,或者,我也可以使用
.git/config
命令删除
git submodule deinit
中的子模块条目,如下所示(它可以执行更多操作,但我认为这与此处无关):

git clone --no-checkout myreop
cd myrepo
git checkout branch001
git submodule update --init
git checkout branch002 
# the .gitmodules file now has the correct changed submodule url but the
# .git/config file has the previous one which is not in sync with .gitmodules

git submodule deinit -f --all
# .gitmodules is unchanged, still correct.
# .git/config submodule entries are now deleted as I expected, which is good

git submodule update --init
# .gitmodules still unchanged and correct
# .git/config is now in sync with .gitmodules again

但令人惊讶的是最后一个命令仍然失败了:

fatal: git upload-pack: not our ref 11ba32ee3c7104f9ce614a393b02624ce09bdcda
fatal: remote error: upload-pack: not our ref 11ba32ee3c7104f9ce614a393b02624ce09bdcda
fatal: Fetched in submodule path 'modulpath', but it did not contain 11ba32ee3c7104f9ce614a393b02624ce09bdcda. Direct fetching of that commit failed.

看起来 old_submodule_repo 仍然存储在某个地方。所以我检查一下:

$ find . -type f -exec grep -l "new_submodule_repo" {} \;
./.git/logs/HEAD
./.git/logs/refs/heads/master
./.git/logs/refs/remotes/origin/HEAD
./.git/config
./.gitlab-ci.yml
./.gitmodules

$ find . -type f -exec grep -l "old_submodule_repo" {} \;
# nothing

好吧,我找到了解决方案:

git submodule sync
而不是
git submodule deinit

但我仍然想知道 git 在哪里存储了旧的子模块 url,以及为什么子模块 origin 指向那里,即使

.git/config
具有正确的 origin url。

当我说

git set-url origin ...
时,我希望这能反映在
.git/config
文件中并得到尊重。如果我直接对
.git/config
文件进行更改,我也希望得到尊重。在这两种情况下,它都受到尊重。但对于子模块,事情似乎不一样了。

所以我的问题是:

  • 为什么
    git submodule deinit
    没有重置子模块 url,尽管
    git submodule sync
    在不删除整个子模块文件夹的情况下可以更方便地完成工作?
  • 旧的子模块 url 存储在哪里?
  • 为什么这个“秘密”商店优先于
    .git/config
  • git submodule deinit -f --all
    不删除子模块的上传包是git的bug吗?
git git-submodules
1个回答
0
投票

看起来 old_submodule_repo 仍然存储在某个地方。所以我做 一张支票:

$ find . -type f -exec grep -l "new_submodule_repo" {} \;
./.git/logs/HEAD 
./.git/logs/refs/heads/master
./.git/logs/refs/remotes/origin/HEAD 
./.git/config 
./.gitlab-ci.yml
./.gitmodules

$ find . -type f -exec grep -l "old_submodule_repo" {} \;
# nothing

第二个命令应该找到

./.git/modules/modulpath/config
,因为这是子模块远程的
remote.origin.url
配置的最终存储位置。我不知道为什么你的调用找不到它(它对我有用)。也许您有非标准设置?

好吧,我找到了解决方案:git submodule sync 而不是 git submodule deinit。

确实,

git submodule sync
会将子模块 URL 从
.gitmodules
复制到
submodule.modulpath.url
中的
.git/config
,然后复制到
remote.origin.url
中的
.git/modules/modulpath/config

但我仍然想知道 git 在哪里存储了旧的子模块 url,以及为什么子模块 origin 指向那里,即使 .git/config 具有正确的 origin url。

它存储在子模块存储库的配置文件中,如上所述。子模块配置文件中的

remote.origin.url
是用于与子模块远程通信的URL的来源。

为什么 git submodule deinit 没有重置子模块 url,尽管 git submodule sync 可以更方便地完成这项工作,而无需删除整个子模块文件夹?

git submodule deinit
只是从超级项目的
sumodule
中删除
.git/config
部分,如 1 中所述。

旧的子模块 url 存储在哪里? 为什么这个“秘密”存储优先于 .git/config?

如上所述,URL 存储在子模块存储库的配置文件中。这不是“秘密”,子模块只是另一个 Git 存储库中的常规 Git 存储库,用于配置远程 URL (

remote.origin.url
) 的相同配置也用于子模块中是有意义的。

git submodule deinit -f --all 没有删除子模块的上传包,是不是git的bug?

“删除子模块的上传包”没有多大意义,upload-pack是

git fetch
调用的Git命令。
git submodule deinit
没有触及子模块的配置文件,这不是一个错误,它只是触及了超级项目的配置文件。

© www.soinside.com 2019 - 2024. All rights reserved.