我有一个文件夹,这是一个git repo。它包含一些文件和.gitmodules文件。现在,当我执行git init
然后git submodule init
时,后一个命令输出什么都不是。如何帮助git查看.gitmodules文件中定义的子模块,而无需再次手动运行git submodule add
?
更新: 这是我的.gitmodules文件:
[submodule "vim-pathogen"]
path = vim-pathogen
url = git://github.com/tpope/vim-pathogen.git
[submodule "bundle/python-mode"]
path = bundle/python-mode
url = git://github.com/klen/python-mode.git
[submodule "bundle/vim-fugitive"]
path = bundle/vim-fugitive
url = git://github.com/tpope/vim-fugitive.git
[submodule "bundle/ctrlp.vim"]
path = bundle/ctrlp.vim
url = git://github.com/kien/ctrlp.vim.git
[submodule "bundle/vim-tomorrow-theme"]
path = bundle/vim-tomorrow-theme
url = git://github.com/chriskempson/vim-tomorrow-theme.git
以下是这个目录的列表:
drwxr-xr-x 4 evgeniuz 100 4096 июня 29 12:06 .
drwx------ 60 evgeniuz 100 4096 июня 29 11:43 ..
drwxr-xr-x 2 evgeniuz 100 4096 июня 29 10:03 autoload
drwxr-xr-x 7 evgeniuz 100 4096 июня 29 12:13 .git
-rw-r--r-- 1 evgeniuz 100 542 июня 29 11:45 .gitmodules
-rw-r--r-- 1 evgeniuz 100 243 июня 29 11:18 .vimrc
所以,当然,它处于最高水平。 git目录未更改,仅完成git init
答案 0 :(得分:89)
git submodule init
仅考虑已经在索引中的子模块(即“暂存”)进行初始化。我会编写一个简短的脚本来解析.gitmodules
,并为每个url
和path
对运行:
git submodule add <url> <path>
例如,您可以使用以下脚本:
#!/bin/sh
set -e
git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
while read path_key path
do
url_key=$(echo $path_key | sed 's/\.path/.url/')
url=$(git config -f .gitmodules --get "$url_key")
git submodule add $url $path
done
这基于git-submodule.sh
script本身如何解析.gitmodules
文件。
答案 1 :(得分:15)
扩展@Mark Longair的答案,我写了一个bash脚本来自动执行第2步和第2步。以下3个过程:
#!/bin/bash
set -e
rm -rf .git
git init
git config -f .gitmodules --get-regexp '^submodule\..*\.path$' > tempfile
while read -u 3 path_key path
do
url_key=$(echo $path_key | sed 's/\.path/.url/')
url=$(git config -f .gitmodules --get "$url_key")
read -p "Are you sure you want to delete $path and re-initialize as a new submodule? " yn
case $yn in
[Yy]* ) rm -rf $path; git submodule add $url $path; echo "$path has been initialized";;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done 3<tempfile
rm tempfile
注意:子模块将在其主分支的顶端检出,而不是与样板回购相同的提交,因此您需要手动执行此操作。
将输出从git config导入读取循环导致输入提示出现问题,因此将其输出到临时文件中。我的第一个bash脚本的任何改进都将非常受欢迎:)
非常感谢Mark,https://stackoverflow.com/a/226724/193494,bash: nested interactive read within a loop that's also using read和tnettenba @ chat.freenode.net帮助我找到解决方案!
答案 2 :(得分:3)
我有类似的问题。 git submodule init
默默地失败了。
当我这样做时:
git submodule add <url> <path>
我得到了:
The following path is ignored by one of your .gitignore files: ...
我认为.gitignore(d)路径可能是原因。
答案 3 :(得分:3)
扩展了出色的@Mark Longair答案,以添加尊重分支和仓库名称的子模块。
undefiend
答案 4 :(得分:2)
@ mark-longair的脚本的更新版本。这个还支持分支,处理.git/config
中已经存在某些子模块的情况,并在必要时备份与子模块路径同名的现有目录。
git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
while read path_key path
do
url_key=$(echo $path_key | sed 's/\.path/.url/');
branch_key=$(echo $path_key | sed 's/\.path/.branch/');
# If the url_key doesn't yet exist then backup up the existing
# directory if necessary and add the submodule
if [ ! $(git config --get "$url_key") ]; then
if [ -d "$path" ] && [ ! $(git config --get "$url_key") ]; then
mv "$path" "$path""_backup_""$(date +'%Y%m%d%H%M%S')";
fi;
url=$(git config -f .gitmodules --get "$url_key");
# If a branch is specified then use that one, otherwise
# default to master
branch=$(git config -f .gitmodules --get "$branch_key");
if [ ! "$branch" ]; then branch="master"; fi;
git submodule add -f -b "$branch" "$url" "$path";
fi;
done;
# In case the submodule exists in .git/config but the url is out of date
git submodule sync;
# Now actually pull all the modules. I used to use this...
#
# git submodule update --init --remote --force --recursive
# ...but the submodules would check out in detached HEAD state and I
# didn't like that, so now I do this...
git submodule foreach --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)';
答案 5 :(得分:1)
我知道它已经有一段时间了,但我想分享这个只调用git config
一次,不需要脚本并处理分支的版本:
git config -f .gitmodules --get-regexp '^submodule\.' | perl -lane'
$conf{$F[0]} = $F[1]}{
@mods = map {s,\.path$,,; $_} grep {/\.path$/} keys(%conf);
sub expand{$i = shift; map {$conf{$i . $_}} qw(.path .url .branch)}
for $i (@mods){
($path, $url, $branch) = expand($i);
print(qq{rm -rf $path});
print(qq{git submodule add -b $branch $url $path});
}
'
唯一的副作用是输出命令,没有执行任何操作,因此您可以在提交之前进行审核。
这可以在控制台上进行简单的复制和粘贴,但是放入shell脚本应该很简单。
示例输出:
rm -rf third-party/dht
git submodule add -b post-0.25-transmission https://github.com/transmission/dht third-party/dht
rm -rf third-party/libutp
git submodule add -b post-3.3-transmission https://github.com/transmission/libutp third-party/libutp
rm -rf third-party/libb64
git submodule add -b post-1.2.1-transmission https://github.com/transmission/libb64 third-party/libb64
rm -rf third-party/libnatpmp
git submodule add -b post-20151025-transmission https://github.com/transmission/libnatpmp third-party/libnatpmp
rm -rf third-party/miniupnpc
git submodule add -b post-2.0.20170509-transmission https://github.com/transmission/miniupnpc third-party/miniupnpc
rm -rf third-party/libevent
git submodule add -b post-2.0.22-transmission https://github.com/transmission/libevent third-party/libevent
答案 6 :(得分:0)
对于zsh用户,请尝试使用支持DRY_RUN=1
的函数来查看将运行哪些命令,并且仅使用git
来解析文件,而不是sed
。
gsub_file() {(
set -eu
cd "$(git rev-parse --show-toplevel)"
submodule_paths=(
"${(@f)$(git config --file ./.gitmodules --get-regexp "path" | awk '{ print $2 }')}"
)
submodule_urls=(
"${(@f)$(git config --file ./.gitmodules --get-regexp "url" | awk '{ print $2 }')}"
)
submodule_branches=(
"${(@f)$(git config --file ./.gitmodules --get-regexp "branch" | awk '{ print $2 }')}"
)
sh_c() {
echo + "$*"
if [ "${DRY_RUN-}" ]; then
return
fi
eval "$@"
}
for (( i=1; i <= ${#submodule_paths[@]}; i++ )) do
p="${submodule_paths[$i]}"
if [ -d "$p" ]; then
continue
fi
url="${submodule_urls[$i]}"
unset b
if [ "${submodule_branches[$i]-}" ]; then
b="-b ${submodule_branches[$i]}"
fi
sh_c git submodule add "${b-}" "$url" "$p"
done
)}