我认为这里的问题是 Git 的设计与您要解决的问题之间的不匹配。
Git 非常适合跟踪树。项目之间的依赖关系可以(并且可能会)形成一个图表。树是图,但图不一定是树。由于您的问题是如何有效地表示图形,因此树不是这项工作的最佳工具。
这是一种可能有效的方法:
一个 git 项目有一个 .gitmodules 目录,它记录“提示”,说明提交可能依赖于哪些项目,可以在哪里找到它们,以及它们应该插入到项目内的哪个路径。( http://osdir.com/ml/git/2009-04/msg00746.html )
您可以添加一个脚本,该脚本从一组项目中读取此信息,将在每个项目的 .gitmodules 文件中找到的提示映射到文件系统上实际放置这些项目的位置,然后从 git 期望的路径添加符号链接将子模块签出到各个项目的实际文件系统位置。
这种方法使用符号链接来打破树模并构建图表。如果我们直接在 git repos 中记录链接,我们将在各个项目中记录特定于本地设置的相对路径,并且项目不会像您想要的那样“完全独立”。因此,动态构建符号链接的脚本。
我认为这种方法可能会以不受欢迎的方式干扰 git,因为我们已经采取了它期望找到一件事的路径,并在那里放了其他东西。也许我们可以 .gitignore 符号链接路径。但是现在我们将这些路径写了两次并违反了 DRY。在这一点上,我们离假装使用子模块还很远。我们可以在每个项目的其他地方记录依赖关系,并将 .gitmodules 文件留给 git 期望的东西。因此,我们将创建自己的文件,例如 .dependencies,每个项目都可以在其中声明其依赖项。我们的脚本会在那里查看,然后去构建它的符号链接。
嗯,我想我可能刚刚描述了一个 ad-hoc 包管理系统,它有自己的轻量级包格式:)
megamic 的建议对我来说似乎很好地使用了 git 子模块。我们在这里只处理跟踪一个集合而不是一个图表,一个集合很容易适合一棵树。一层深的树本质上是一个父节点和一组子节点。
正如您所指出的,这并不能完全解决您的问题中所述的问题。我们可以分解出我们可能感兴趣的两种不同类型的“这与那个一起工作”信息: 1. 来自项目版本的声明(可能是项目作者)说“我需要项目 Y 的版本 X”2 . 您自己的构建设置使用的声明“我已经使用这组项目版本成功测试了我们的整个系统”
megamic 的答案解决了 (2) 但对于 (1) 我们仍然希望项目告诉我们它们的依赖关系是什么。然后我们可以使用来自 (1) 的信息来计算我们最终将记录为 (2) 的那些版本集。这是一个足够复杂的问题,需要有自己的工具,这让我们回到包管理系统:)
据我所知,大多数优秀的包管理工具都是为特定语言或操作系统的用户设计的。请参阅 Bundler 以获取 ruby 世界中的“gem”包和 apt 以获取 Debian 世界中的“.deb”包。
如果有人知道一个很好的语言中立、操作系统中立的解决方案,它非常适合“多语言”(http://blog.heroku.com/archives/2011/8/3/polyglot_platform/)编程项目,我会很感兴趣的!我应该把它作为一个问题发布。