不同的分支是否每个都有自己的子模块URL,并且仍然可以轻松切换



我有一个git中的子模块,我希望能够让不同的分支为这个子模块指定不同的URL,在.gitmodules中指定。我知道这是可能的,但现在每当我在这些分支之间切换时,都需要整个过程才能将子模块放到正确的哈希中。我必须卸载子模块,删除.git/下的模块路径,然后重新编译,这需要一段时间。考虑到每个分支使用不同的子模块URL,有没有一种更容易的方法来切换分支并获得正确的哈希?

分支——我指的是分支名称——在这里不相关1重要的是提交。。。不幸的是,在您自己的案例中,检查每个提交的特定模式。

子模块无非是一个单独的Git存储库。如果您还没有子模块,Git必须运行git clone才能获得它,Git通过以gitlink的形式组合某个特定提交中的信息来找到该git clone命令的指令,该路径类似于path/to/submodule,其条目为mode 160000,即gitlink,带有一些哈希ID,加上名为.gitmodules的文件中同一提交的信息。

让我们举一个例子。假设超级存储库名为super,在提交a123456时,path/to/sub的模式为160000,表示为commit 5555555。克隆超级项目并签出提交a123456。子模块尚未被克隆,但超级项目的索引显示";我们需要为CCD_ 12提交CCD_;此时。

如果你现在运行git submodule update --init(或者已经使用递归克隆为你做了这件事(,Git现在会注意到,嘿,存储库还没有克隆,所以它在.gitmodules中查找path/to/sub来找到克隆它的指令。然后,它使用(实际上(--no-checkout运行git clone,然后进入子模块并检查提交5555555(通过原始哈希ID(。

但现在path/to/sub被克隆的子模块相关联。假设您现在在super中签出提交b789abc,并且说";使用提交CCD_ 22";。这进入了Git的索引(对于super:子模块sub的索引和工作树还没有被修改(。如果您现在运行git submodule update,或者启用了递归签出(这对您来说是这样做的(,Git会注意到子模块已经被克隆,并且不需要从b789abc中查找.gitmodules文件。

请注意,如果在提交a123456时没有运行git submodule update --init,则子模块还不会被克隆。因此,super中的操作现在将查看提交b789abc中出现的.gitmodules文件,该文件可能具有完全不同的URL。Git会克隆URL,并在那里查找提交5678567

这就是你试图解决的问题。除了你一直在使用的可怕的手动流程之外,没有其他解决方法。

(这个问题的常见术语是,你有一个"路径依赖的结果"。Git没有预料到这一点,只是没有正确处理它。(


1特别是,多个分支名称可以指向同一提交。如果maindevelop都指向提交a123456,那么使用哪个名称就无关紧要了,因为无论哪种方式都可以提交a123456。分支名称会随时间移动,因此main今天识别a123456并不意味着它明天会识别a123456

一种解决方案是为每个不同的源URL使用不同的子模块名称

例如,假设我有时想要使用来自源url_a的包pkg,有时使用从源url_b获取的pkg。我将首先在我的存储库中创建两个独立的子模块pkg_from_apkg_from_b

git submodule add <url_a> pkg_from_a
git submodule add <url_b> pkg_from_b

现在我有两个独立的子模块,但如何选择正在使用的子模块?这是通过根据需要创建指向pkg_from_apkg_from_b的符号链路pkg来完成的。例如,如果我从一个应该使用pkg_from_a的分支开始,我会创建并提交这样的链接:

ln -s pkg_from_a pkg     # NOTE: Unix syntax for creating a symbolic link
git add pkg
git commit pkg

修改链接是在两个子模块之间切换所必需的全部内容。链接可以在逐个提交的基础上更改,因此不同的分支可以轻松地使用来自不同位置的pkg

相关内容

  • 没有找到相关文章