引言
当使用
git clone --recursive url
拉取一个配置了子模块的仓库后,会卡住。
同时在使用
git clone
拉去
https
的
url
时,同样可能会出现一直卡在
cloning int reposity...
本文提供一个简单的脚本来解决该问题。
前置准备
需要配置好
git
的相关配置,
git user.name
,
git user.email
,
ssh
。
问题一 使用git clone拉去https协议仓库时卡住
以
mxnet
的仓库为例,如果使用
https
协议进行克隆,即通过命令
https://github.com/apache/mxnet.git
,可能会出现卡在
cloning into mxnet...
的情况。其实解决方法很简单,当将上面
https
协议的
url
改成
ssh
协议即可,即使用命令
git clone [email protected]:apache/mxnet.git
这样就不会卡住了,但是原理目前并不是很清楚。
注:即使使用
ssh
进行仓库的克隆,也是需要非常手段。同时需要配置
ssh
。
问题二 拉取submodules时卡住
拉取子模块卡住还是因为在原始仓库中的配置中使用了
https
协议的仓库链接进行拉取,想要解决实际上只需要将仓库中的
.gitmodules
文件中的所有子模块的
url
改成
ssh
协议进行拉取即可。
修改只需要将
url
中的
https:://github.com/
替换成
[email protected]:
,但是手动修改的话比较麻烦,因为修改之后需要考虑拉取的子模块也会依赖其他子模块的情况,此时则还需要修改,因此本人简单写了一个脚本,通过递归来实现。代码如下:
#!/bin/bashpull_submodule_recursive(){if[-f".gitmodules"];thenecho".gitmodules found"# backupcp .gitmodules .gitmodules.bak
whileread line
do# substitude the https with sshecho${line}|sed's/https:\/\/github.com\//[email protected]:/g'>> .new_gitmodules
done< .gitmodules
mv .new_gitmodules .gitmodules
# pull current submodulesgit submodule init
git submodule syncgit submodule update
# get the directories of current submoduleslocaldirectories=$(cat .gitmodules |grep path |awk'{print $3}')fordirectoryin$directoriesdoif[-d$directory];then# enter the directorypushd${directory}> /dev/null
# pull one submodule and its submodules
pull_submodule_recursive
# return to the last working directorypopd> /dev/null
fidoneelseecho"current submodule has no submodule, return to last directory..."fireturn0}
pull_submodule_recursive
脚本的使用方法,以拉取
mxnet
为例:
- 首先需要将不含有子模块的
mxnet
拉取下来,注意需要使用ssh
进行拉取,即使用命令:git clone [email protected]:apache/mxnet.git
; - 进入到仓库路径,此时会在当前目录下出现
mxnet
目录,只需要进入该目录,创建一个文件,将上面的代码拷贝到文件中,这里我们把名字设置为get_submodules_recursive
; - 执行上述脚本,等待子模块拉取完成,一定要使用
bash
来执行,sh
不支持pushd
和popd
命令会出现错误,即通过命令bash get_submodules_recursive
进行执行。
执行效果如下图:
能够看到此时遍能够成功拉去子模块了,此时
git status
会显示有新的修改,因为修改了
.gitsubmodules
文件,不过这个问题不大,如果觉得不想修改的话,只需要根据提示通过
git restore
命令恢复即可
代码逻辑解释
代码会查找当前目录下的
.gitmodules
文件,只有找到改文件才回继续进行执行,当找到改文件后,会将改文件中的子模块的
url
改成
ssh
协议,更改完成后进行子模块的拉取,拉取后进入到每个子模块中进行检查子模块是否还有子模块…代码会一直重复上述的逻辑,知道所有的子模块全部拉取完成。
也就是代码执行的逻辑与
git clone --recursive
一致只是在每次拉去的时候需要修改
.gitmodles
中的
url
。
可悲
版权归原作者 kaiserqzyue 所有, 如有侵权,请联系我们删除。