如何使用子模块克隆本地存储库?
How do I clone a local repo with submodules?
假设我递归地克隆了一个存储库。
$ 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'
现在我想创建该本地存储库的本地克隆(可能在本地进行并提交更改之后)。
$ 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
为什么会失败,我该如何解决这个问题?
问题出在您的 .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
应该就可以了!
我需要一个比这更全面的解决方案,因为 gitlab 克隆东西的方式很奇怪(SRC 是顶层源回购文件夹,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;
如果有一个内置的方法来做到这一点就好了...
注意:对于 Git 2.12 或更低版本,此 git submodule update --init --recursive
可能会因为子模块的某些异常路径而失败。
此问题已在 Git 2.13(2017 年第二季度)
中修复
参见 commit cf9e55f (07 Apr 2017) by Brandon Williams (mbrandonw
)。
(由 Junio C Hamano -- gitster
-- in commit 5bceab4 合并,2017 年 4 月 24 日)
submodule
: prevent backslash expansion in submodule names
When attempting to add a submodule with backslashes in its name 'git submodule
' fails in a funny way. We can see that some of the
backslashes are expanded resulting in a bogus path:
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
To solve this, convert calls to 'read
' to 'read -r
' in git-submodule.sh
in order to prevent backslash expansion in submodule names.
如果我们要从本地克隆的子模块中克隆子模块,我来下面这个版本。这只允许一级子模块。
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
假设我递归地克隆了一个存储库。
$ 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'
现在我想创建该本地存储库的本地克隆(可能在本地进行并提交更改之后)。
$ 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
为什么会失败,我该如何解决这个问题?
问题出在您的 .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
应该就可以了!
我需要一个比这更全面的解决方案,因为 gitlab 克隆东西的方式很奇怪(SRC 是顶层源回购文件夹,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;
如果有一个内置的方法来做到这一点就好了...
注意:对于 Git 2.12 或更低版本,此 git submodule update --init --recursive
可能会因为子模块的某些异常路径而失败。
此问题已在 Git 2.13(2017 年第二季度)
参见 commit cf9e55f (07 Apr 2017) by Brandon Williams (mbrandonw
)。
(由 Junio C Hamano -- gitster
-- in commit 5bceab4 合并,2017 年 4 月 24 日)
submodule
: prevent backslash expansion in submodule namesWhen attempting to add a submodule with backslashes in its name '
git submodule
' fails in a funny way. We can see that some of the backslashes are expanded resulting in a bogus path:
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
To solve this, convert calls to '
read
' to 'read -r
' ingit-submodule.sh
in order to prevent backslash expansion in submodule names.
如果我们要从本地克隆的子模块中克隆子模块,我来下面这个版本。这只允许一级子模块。
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