已知Git子模块URL,如何获取对应的子模块路径?
如何通过已知URL获取Git子模块的路径
问题背景
已知.gitmodules文件内容示例如下:
[submodule "foo"] path = app/foo url = https://my-known-url branch = main
当前使用grep命令实现需求,但该方法依赖文本格式,稳定性不足:
cat .gitmodules | grep -B 1 -A 1 my-known-url | grep path | cut -d'=' -f 2 | xargs
尝试使用git config --file .gitmodules命令未成功,且需要兼容以git@ssh.dev.azure.com:v3开头的Azure DevOps SSH源地址(例如--get-urlmatch似乎不支持该格式)。
稳定解决方案
方案1:利用Git Config命令遍历匹配
通过Git自身的配置解析能力遍历所有子模块,匹配目标URL后输出对应路径,兼容所有合法Git URL格式:
TARGET_URL="git@ssh.dev.azure.com:v3/your-org/your-repo" git config --file .gitmodules --get-regexp 'submodule\..*\.url' | while read -r config_key actual_url; do if [ "$actual_url" = "$TARGET_URL" ]; then # 提取子模块名称 submodule_name=$(echo "$config_key" | sed 's/submodule\.\(.*\)\.url/\1/') # 获取对应路径 git config --file .gitmodules "submodule.$submodule_name.path" fi done
方案2:用AWK解析.gitmodules文件
直接解析配置文件格式,不依赖Git版本,处理逻辑更可控:
TARGET_URL="git@ssh.dev.azure.com:v3/your-org/your-repo" awk -v target="$TARGET_URL" ' /^\[submodule/ { in_submodule = 1 current_path = "" current_url = "" } in_submodule { if ($1 == "path") { current_path = substr($0, index($0, "=")+1) gsub(/^[ \t]+|[ \t]+$/, "", current_path) } if ($1 == "url") { current_url = substr($0, index($0, "=")+1) gsub(/^[ \t]+|[ \t]+$/, "", current_url) } if (current_path != "" && current_url != "") { if (current_url == target) { print current_path } in_submodule = 0 } } ' .gitmodules
方案优势
- 避免了grep依赖上下文行的不稳定问题,即使子模块配置项顺序变化也能正常工作
- 完美兼容HTTPS、SSH等所有Git URL格式,包括Azure DevOps的SSH地址
- 两种方案分别利用Git原生能力和通用文本解析工具,可根据场景选择
内容的提问来源于stack exchange,提问作者The Fool
相关产品推荐
相关产品推荐

