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

Posted

技术标签:

【中文标题】子模块内的 Git 子模块(嵌套子模块)【英文标题】:Git submodule inside of a submodule (nested submodules) 【发布时间】:2010-12-04 20:46:20 【问题描述】:

一个 git 子模块是否可以由几个其他 git 子模块组成,超级 git repo 可以获取每个子模块的内容?

我尝试使用明显/幼稚的方法来创建包含多个子模块的 git 存储库。

然后将此 git repo 作为子模块添加到另一个 git repo。

然后尝试通过git submodule initgit submodule update 从超级git repo 的根目录中拉取。但这无法获取子子模块。

【问题讨论】:

我建议你使用 TortoiseGit——在你的根目录中使用它,然后要求它更新所有子模块,包括初始化、递归、强制检查! 【参考方案1】:

如Retrospectively add --recursive to a git repo中所述

git submodule update --init --recursive

应该可以。

【讨论】:

这对我有用。请注意,我错误地认为git submodule init; git submodule update --recursive 是上述的同义词,但事实并非如此。 +1 我喜欢这个比我使用的要好得多: git submodule foreach git submodule init ... 然后 git submodule update --recursive 不幸的是,这对我不起作用。没有错误,没有消息,什么都没有。 您如何更新这些完全嵌套的存储库?当我传入--init 标志时,我的一个子模块中的子模块只会初始化为旧版本,而不是最新版本。 我做git submodule foreach git pull origin master,它部分工作:子模块已更新,但有时HEAD 被分离,对于子模块中的子模块,我无法提交我的直接子模块的更改,因为它有“修改内容”而不是“新提交”(因为它自己的子模块有“新提交”并已更新)。【参考方案2】:

正如下面的Sridhar cmets,来自Git1.6.5+,git clone --recursive现在是官方的替代品,描述在:

git clone --submodule” “Retrospectively add --recursive to a git repo” (使用 alias $ git config --global alias.cloner = 'clone --recursive',可避免影响正常的 git clone 命令)

inamiy 正确 points out git submodule update --init --recursive 命令,在 commit b13fd5c 中引入,再次在 git1.6.5 中由 Johan Herland (jherland) 引入。

而IceFire 添加in the comments:

如果您只想签出一个子模块的一个子模块,那么git submodule update --init <submoduleName> 是最好的选择。


(较早的原始答案)

根据manual page

 git submodule update --recursive

应该更新任何嵌套的子模块。但 init 部分可能不是递归的。

根据您的 Git 版本,您可以回退到更“脚本化”的方法,这篇文章 Recursively Updating Git Submodules 允许递归初始化和更新:

#!/usr/bin/perl

use strict;
use Cwd;

init_and_update();

exit;

sub init_and_update

    my $start_path = cwd();

    my %paths;
    my $updated;

    do
    
        my $data = `find . -name '.gitmodules'`;
        chomp($data);

        $data =~ s/\/\.gitmodules//g;

        foreach my $path (split(/\n/, $data))
        
            $paths$path = '' if($paths$path eq '');
        

        $updated = 0;

        foreach my $path (sort keys %paths)
        
            if($paths$path eq '')
            
                chdir($path);
                `git submodule init 2>&1`;
                `git submodule update 2>&1`;
                chdir($start_path);

                if($ARGV[0] eq '--remove-gitmodules')
                
                    unlink("$path/.gitmodules");
                

                $paths$path = 1;

                $updated++;
            
        
     while($updated);

【讨论】:

git clone --recursive 还不够吗? @Sridhar:用于克隆,如***.com/questions/3796927/git-clone-submodule 和***.com/questions/4251940/… 中所述,来自 Git1.6.5 及更高版本。我已经编辑了我的答案以反映这一点。 注意:如果您只想签出一个子模块的一个子模块,那么git submodule update --init <submoduleName> 是要走的路;我在寻找这个答案时来到这里 @IceFire 谢谢。我已将您的评论包含在答案中以提高知名度。

以上是关于子模块内的 Git 子模块(嵌套子模块)的主要内容,如果未能解决你的问题,请参考以下文章

使用git子模块管理项目

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

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

使用 Git 复制子模块

git 子模块操作

手把手教你把 Git 子模块更新到主项目