没有远程仓库的嵌套git仓库(也称为没有远程仓库的git子模块)

51

我有一个项目,我希望将其中的一部分作为开源发布。我已经设置好了嵌套的git仓库,包括主仓库、一号仓库、二号仓库和三号仓库:

main/
├── one
├── three
└── two

我认为通过进入“main”并执行以下操作:

git add one
git add two
git add three

需要注意的是,没有尾随斜线,在子仓库中设置submodule即可。

但是,正如在如何跟踪未跟踪的内容中所指出的那样,这只会创建git链接而不是真正的submodules。

不幸的是,这个答案并没有帮助,因为它假定有一个“主”存储库位于其他地方,对于“main / one”,“main / two”和“main / three”我希望这些子存储库成为主存储库。 我正在考虑使用伪子模块(如Git fake submodules中所述),但对于克隆来说这不是一个特别理想的情况。

还有其他建议吗?

4个回答

35
你可以按照自己的意愿去做,但是你的onetwothree需要对需要克隆它们的人可访问 - 这通常不适用于“随机”的开发存储库。如果你设置了这个,你需要非常小心,不要删除“你的”存储库(或使其无法访问),因为它不仅仅是“你的”,它还将成为你的协作者克隆版本中的origin,并且它将作为“中央”/“上游”存储库(如.gitmodules中指定)。
如果所有的合作者都是本地的(并且能够从存储库中读取),你可以通过将它们的本地路径作为URL来将现有的子存储库添加为子模块。
git rm --cached one two three
git submodule add `pwd`/one
git submodule add `pwd`/two
git submodule add `pwd`/three
如果你的协作者并非都在同一台机器上工作,那么这种方法可能行不通(因为它将在.gitmodules文件中存储一个本地路径;不在本地的协作者必须在git submodule init后调整URL)。如果你的one、two和three是可以通过Git远程访问的,则可以指定其有效的URL。
git rm --cached one two three
git -c protocol.file.allow=always submodule add server:/path/to/your/main/one
git -c protocol.file.allow=always submodule add server:/path/to/your/main/two
git -c protocol.file.allow=always submodule add server:/path/to/your/main/three

在这两种情况下,由于您已经有一个子存储库,git submodule add 将使用该存储库,而不是尝试从指定的路径/URL克隆。


е‡ғдғҺеӨҢеӨ‡пәЊењЁжњЂеқЏзљ„情况下пәЊеђ€дҢњиЂ…иѓҢ否手动зә–иң‘.gitmodulesе’Њ.git/configжқӨ“дү®е¤ҚвЂқжҚџеқЏзљ„й“ңжҺӨпәџ - David Alan Hjelle
6
@David:1)使用相对路径添加子模块对于 git submodule add 来说意味着将其解析为包含仓库的 origin 远程的相对路径。这就是我在例子中使用 pwd 获取绝对路径的原因。2)是的,你的协作者在初始化子模块后始终可以编辑 .git/config。如果你为子仓库建立了一个广泛可用的 URL(或者决定将裸库放在广泛可访问的位置),那么应该更新 .gitmodules,这样未来克隆你的主仓库的协作者就不必手动调整 URL。 - Chris Johnsen
2
简而言之:除非所有合作者共享一台机器,否则无法在没有远程的情况下实现。 - Ryne Everett
2
请注意,对于较新版本的git(例如我的v2.38.1),当尝试添加本地子模块路径时,“file”协议默认被阻止。使用上述子模块命令将会出现错误,类似于“Cloning into '/tmp/repo1/sub'... fatal: transport 'file' not allowed fatal: clone of '/tmp/repo2' into submodule path '/tmp/repo1/sub' failed”。为了避免这种情况,需要使用-c选项来覆盖protocol.file.allow配置属性,例如:git -c protocol.file.allow=always submodule add --name subrepo /tmp/repo2 path-under-parent-repo - zpangwin
1
@zpangwin 我已将此编辑为答案。这是在git中进行更改的参考 - Him
显示剩余2条评论

6

Chris回答 不假设存在一个名为"master" 的仓库(master 是 Git 中主分支的默认名称,而不是一个仓库)。

它在一个“parent”仓库中声明了子模块,在您的情况下,这个“parent”仓库将是“main”。

因此,您需要在其他地方设置三个独立的仓库 "one"、"two" 和 "three",然后将它们作为子模块克隆并添加到您的“main”仓库中:

# first remove the one directory previously added
git rm --cached one
# then declare the external one repo as a submodule in "main" repo)
git submodule add /path/to/one.git one

是的,那是一种处理方法——但是如果可能的话,我正试图避免在其他地方设置仓库。 (我没有看到任何理由让额外的仓库四处躺着)。 不过,还是谢谢您的贡献! - David Alan Hjelle

1

我刚想到一个主意,将子模块的存储库放置在超级项目的子目录中。这样,整个项目仅依赖于您设置的一个存储库/位置(根据Chris的回答)。

例如,子模块one的主要存储库将位于位置server:/path/to/your/main/one(通过该目录中的git remote -v)。

这样,submodule功能(例如git submodule update --recursive)也会指向正确的位置,因为该模块/存储库的URL指向./one(.gitmodules)。


1
我相信你所描述的是被称为“单体仓库”。 - vhs

0
在我的情况下,我需要同时指定子模块的地址和它应该被克隆到的位置,而且这两者是相同的。
$ git submodule add ./path/to/submodule path/to/submodule
Adding existing repo at 'path/to/submodule' to the index

更多关于我的使用情况的细节: 我想要开始使用git跟踪一个已存在的文件夹,而这个文件夹已经包含了仓库。我希望将所有内容保留在本地:我并不与任何人在这些仓库上进行协作,而且这些文件夹已经在云端保存了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接