使用 Git 复制子模块

Posted

技术标签:

【中文标题】使用 Git 复制子模块【英文标题】:Duplicate submodules with Git 【发布时间】:2010-11-06 23:55:33 【问题描述】:

我在 Git 中有一个项目,它有几个子模块,我需要下载这些子模块和可用的文件才能使用主项目,并且为了使子模块工作,我需要它们自己的子模块可用等等。所以为了设置它,我使用git submodule update --init --recursive递归初始化子模块。

但是,我注意到我的许多子模块都有共享依赖项,在伪代码中看起来像这样(alpha -> beta 表示alpha 具有子模块beta

my project -> submodule a -> submodule m
           -> submodule b -> submodule m
                          -> submodule n -> submodule x
           -> submodule c -> submodule x

我的问题是:有没有什么方法可以避免这种重复,只使用 git,同时仍然拥有(至少一个副本)每个子模块的文件?

我可以想象一个带有符号链接的解决方案,但如果 git 为我处理这个问题会更好,而且我不确定自己放入符号链接是否会在更新子模块时导致问题。

理想情况下,我希望将其简化为:

my project -> submodule a -> symlink(submodule m)
           -> submodule b -> symlink(submodule m)
                          -> symlink(submodule n)
           -> submodule c -> symlink(submodule x)
           -> submodule m
           -> submodule n -> symlink(submodule x)
           -> submodule x

提前感谢您的任何建议!

【问题讨论】:

不是完全相同的问题,但非常相似:***.com/questions/1419498/… 【参考方案1】:

这不是 git 内置的,但你绝对可以像你说的那样使用符号链接来做到这一点。你可能想看看git new-workdir(来自 git 的 contrib 目录),它本质上就是这样做的。它不知道与子模块有任何关系,但子模块不知道它是一个子模块——它是知道这些东西的父 repo。我还没有尝试过,但我相当肯定你可以像这样使用它:

# remove the target first (new-workdir will refuse to overwrite)
rm -rf submodule_b/submodule_m

#               (original repo)         (symlinked repo)
git new-workdir submodule_a/submodule_m submodule_b/submodule_m

它通过符号链接基本上所有 .git 目录来工作;没有符号链接的值得注意的事情是HEAD;这两个目录可以签出不同的内容,但共享相同的引用和对象。

从这里你应该很好。当您在超级模块中运行git submodule 命令时,它只会进入子模块并在那里运行适当的命令,这一切都会按预期工作。

对于像这样的符号链接存储库,您通常需要注意的一件事是它们共享相同的分支集,因此如果它们都签出相同的分支,并且您在一个中提交,另一个将变得不同步。但是,对于子模块,这通常不会成为问题,因为除非您进行干预,否则它们基本上始终处于分离的 HEAD 状态。

【讨论】:

【参考方案2】:

git-new-workdir 可能不是这里讨论的好解决方案: http://comments.gmane.org/gmane.comp.version-control.git/196019

在 git 1.7.10 下它对我不起作用。

我已经使用硬链接为我的用例解决了这个问题。我正在运行 OS X 并且文件系统允许创建到目录的硬链接: https://github.com/darwin/hlink

现在我可以硬链接子模块目录并且 git 透明地对待它们。硬链接还具有很好的特性,即所有子模块都完全镜像,包括 HEAD,这是我更喜欢的一种行为。

好的,我们的想法是拥有一个“主”子模块存储库并将所有“从属”副本硬链接回它。这将使它们彼此无法区分并完全同步。

注意事项

1) 只要 .git 中的相对路径有效,它就可以正常工作。换句话说,您只能硬链接位于目录树中同一目录级别的子模块。这是我的情况。我假设您可以通过使用硬链接任务修改 .gitfiles 来轻松修复它。注意:这在 git 1.7.10 之前应该没有问题,因为之前子模块的 .git 是一个独立的目录,而不仅仅是指向其他地方的纯文本 .git 文件。

2) 硬链接可能会引入一些不兼容性。例如,TimeMachine 会感到困惑,因为它在内部使用硬链接进行版本控制。确保从 TimeMachine 中排除项目目录。

这是我的 rake 任务完成工作的示例: https://github.com/binaryage/site/blob/3ef664693cafc972d05c57a64c41e89b1c947bfc/rakefile#L94-115

【讨论】:

以上是关于使用 Git 复制子模块的主要内容,如果未能解决你的问题,请参考以下文章

将公共代码添加为 git 子模块的问题:“索引中已存在”

子模块内的 Git 子模块(嵌套子模块)

使用git子模块管理项目

git中submodule子模块的添加使用和删除

git中submodule子模块的添加使用和删除

git中submodule子模块的添加使用和删除