如何使用子模块克隆本地存储库?

时间:2016-07-05 16:52:35

标签: git git-submodules git-clone

说我递归克隆了一个回购。

$ git clone --recursive ssh://server/project/client
Cloning into 'client'...
remote: Counting objects: 191, done
remote: Finding sources: 100% (191/191)
remote: Total 191 (delta 53), reused 159 (delta 53)
Receiving objects: 100% (191/191), 27.59 KiB | 0 bytes/s, done.
Resolving deltas: 100% (53/53), done.
Checking connectivity... done.
Submodule 'gui' (ssh://server/project/client/gui.git) registered for path 'gui'
Cloning into 'gui'...
remote: Counting objects: 3213, done
remote: Finding sources: 100% (3213/3213)
remote: Total 3213 (delta 1272), reused 3107 (delta 1272)
Receiving objects: 100% (3213/3213), 47.88 MiB | 12.05 MiB/s, done.
Resolving deltas: 100% (1272/1272), done.
Checking connectivity... done.
Submodule path 'gui': checked out '7315db8d7a8b36929f7874dc5477359839ec51ce'

现在我想创建一个本地repo的本地克隆(可能是在本地制作和提交更改之后)。

$ git clone --recursive client/ client_copy
Cloning into 'client_copy'...
done.
Submodule 'gui' (/home/deployer/client/gui.git) registered for path 'gui'
fatal: repository '/home/deployer/client/gui.git' does not exist
Clone of '/home/deployer/client/gui.git' into submodule path 'gui' failed

我的.gitmodules文件如下所示:

[submodule "gui"]
        path = gui
        url = ../client/gui.git

为什么会失败,我该如何解决这个问题?

4 个答案:

答案 0 :(得分:4)

问题在于您的.gitmodules文件。项目中的子模块url被定义为来自超级项目存储库的相对路径,但是当克隆子模块时,它们将使用path位置放置。

换句话说,git正试图从url位置提取子模块,但在本地计算机上,它们实际上位于path位置。

要解决此问题,请仅克隆本地超级项目存储库(git clone /path/to/superproject),然后转到新克隆的.gitsubmodules并将url更改为./<whatever-the-path-is>。例如,您的gui子模块将变为:

[submodule "gui"]
        path = gui
        url = ./gui

.gitmodules中的每个子模块更改为这样,然后运行:

git submodule sync
git submodule update --init --recursive

那应该这样做!

答案 1 :(得分:0)

我需要一个比这更全面的解决方案,因为gitlab克隆东西的方式很奇怪(SRC是顶层源repo文件夹而DST是请求的顶层目标文件夹):

git clone $SRC $DST
MODULES=$(git -C $SRC config --file .gitmodules --name-only --get-regexp url)
for MODULE in ${MODULES}; do
    MODULE_PATH=$(git -C $SRC config ${MODULE});
    git -C $DST config ${MODULE} ${MODULE_PATH};
done
git -C $DST submodule update --init --recursive;

如果有一种内置的方法可以做到这一点会很棒......

答案 2 :(得分:0)

注意:使用Git 2.12或更低版本时,由于子模块的某些异常路径,此git submodule update --init --recursive可能会失败。
这在Git 2.13(2017年第二季度)

中得到修复

commit cf9e55fBrandon Williams (mbrandonw)(2017年4月7日) Junio C Hamano -- gitster --于2017年4月24日commit 5bceab4合并)

  

submodule:防止子模块名称中的反斜杠扩展

     

尝试在名称中添加带反斜杠的子模块&#39; git submodule&#39;以一种有趣的方式失败。我们可以看到一些   反斜杠被扩展导致伪造路径:

git -C main submodule add ../sub\\with\\backslash
fatal: repository '/tmp/test/sub\witackslash' does not exist
fatal: clone of '/tmp/test/sub\witackslash' into submodule path
  

要解决此问题,请将来电转换为&#39; read&#39;到&#39; read -r&#39;在git-submodule.sh中,以防止子模块名称中的反斜杠扩展。

答案 3 :(得分:0)

如果我们想从本地克隆的子模块中克隆子模块,请参考以下版本。这仅允许一个级别的子模块。

git clone $src $dst
modules=$(git -C $src config --file .gitmodules --name-only --get-regexp url)
for module in $modules; do
  module_path=$(git -C $src config --file .gitmodules ${module%.url}.path)
  git -C $dst config ${module} $src/$module_path
done
git -C $dst submodule update --init