使用 Git 复制子模块
我在 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
提前感谢您的任何建议!
I have a project in Git that has several submodules, and I need those submodules to be downloaded and the files available in order to use the main project, and in order for the submodules to work I need their own submodules to be available etc. So to set this up I recursively initialise the submodules using git submodule update --init --recursive
.
However, I've noticed that many of my submodules have shared dependencies, looking something like this in pseudocode (alpha -> beta
represents that alpha
has the submodule beta
)
my project -> submodule a -> submodule m
-> submodule b -> submodule m
-> submodule n -> submodule x
-> submodule c -> submodule x
My question is: is there any way of avoiding this duplication using only git, while still having (at least one copy of) the files for each submodule?
I can imagine a solution with symlinks, but it would be preferable if git handled this for me, and I'm not sure whether putting in the symlinks myself would cause problems when updating the submodules.
Ideally I'd love to simplify it down to:
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
Thanks in advance for any suggestions!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这不是内置在 git 中的,但是你绝对可以像你说的那样使用符号链接来做到这一点。您可能想看看
git new-workdir
(来自 git 的 contrib 目录),它基本上就是这样做的。它不知道与子模块有关的任何事情,但是子模块不知道它是子模块 - 它是父存储库知道这些东西。我还没有尝试过这个,但我相当确定你可以像这样使用它:它通过符号链接基本上所有 .git 目录来工作;值得注意的是,没有符号链接的是
HEAD
;这两个目录可以检出不同的内容,但共享相同的引用和对象。从这里开始,你应该表现得很好。当您在超级模块中运行 git submodule 命令时,它只会进入子模块并在那里运行适当的命令,这一切都会按预期工作。
对于像这样的符号链接存储库,您通常需要注意的一件事是它们共享同一组分支,因此如果它们都签出了相同的分支,并且您在其中一个中提交了它,则另一个将变得不可用同步。不过,对于子模块来说,这通常不会成为问题,因为除非您干预,否则它们本质上始终处于分离的 HEAD 状态。
This isn't built into git, but you can definitely do it with symlinks like you say. You might want to have a look at
git new-workdir
(from git's contrib directory), which does essentially this. It's not aware of anything to do with submodules, but a submodule doesn't know it's a submodule - it's the parent repo that knows about that stuff. I haven't tried this, but I'm fairly certain you could use it something like this:It works by symlinking essentially all of the .git directory; the notable thing that isn't symlinked is
HEAD
; the two directories can have different things checked out, but share the same refs and objects.From here you should be good. When you run a
git submodule
command in the supermodule, it just goes into the submodules and runs appropriate commands there, which will all work as expected.The one thing you usually need to be aware of with symlinked repos like this is that they share the same set of branches, so if they both have the same branch checked out, and you commit to it in one, the other will become out of sync. With submodules this generally won't be a problem, though, since they're essentially always in detached HEAD state unless you intervene.
正如这里所讨论的,
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/3ef664693cafc972d05c57a64c41e89b 1c947bfc/rakefile #L94-115
git-new-workdir
might not be good solution as discussed here:http://comments.gmane.org/gmane.comp.version-control.git/196019
It didn't work for me under git 1.7.10.
I have solved it for my use-case using hard links. I'm running OS X and the filesystem allows creating hard-links to directories:
https://github.com/darwin/hlink
Now I can hard-link submodule directories and git treats them transparently. Hard linking has also nice property that all submodules are fully mirrored including HEAD which is a behavior I prefer in my case.
Ok, the idea is to have one "master" submodule repo and hard-link all "slave" copies back to it. This will make them all indistinguishable from each other and fully synced.
CAVEATS:
1) This works fine as long as relative paths in .git work. In other words you can hard-link only submodules sitting on same directory level in the directory tree. This was my case. I assume you can easily fix it by modifying .gitfiles with your hard-linking task. Note: This should be no issue before git 1.7.10, because previously submodule's .git was a self-contained directory not just plaintext .git file pointing somewhere else.
2) Hard links may introduce some incompatibilities. For example TimeMachine gets confused because it uses hard links internally for versioning. Make sure you exclude your project directory form TimeMachine.
Here is an example of my rake task doing the job:
https://github.com/binaryage/site/blob/3ef664693cafc972d05c57a64c41e89b1c947bfc/rakefile#L94-115