git中是否有任何方法可以知道你是否在子模块中?您可以像父目录中的git submodule foreach
一样进行思考,但如果您在一个子目录中,或者在任何子目录中,我似乎无法想出一个通用的方法来表明您在子模块中在子模块内。
我猜你可以找到带有git rev-parse --show-toplevel
的repo root,然后再升级一个级别,然后再次查找该repo的根目录,然后将子模块列表与当前目录进行比较,但似乎这么粘......
答案 0 :(得分:20)
(2017年4月更新为Git 2.13,2017年第2季度)
现在有一个官方命令来确定回购是否是父回购的子模块:
cd /path/to/potential/submodule/repo
git rev-parse --show-superproject-working-tree
commit bf0231c见Stefan Beller (stefanbeller
)(2017年3月8日)
(Junio C Hamano -- gitster
--于2017年3月17日commit 3edcc04合并)
rev-parse
:添加--show-superproject-working-tree
在某些情况下,知道给定的存储库是否有用 是另一个存储库的子模块。
将标记
--show-superproject-working-tree
添加到git-rev-parse
,以便轻松找出是否存在超级项目。
如果不存在超级项目,则输出将为空。
获取超级项目路径,无论子模块内部/外部:
git rev-parse --show-superproject-working-tree --show-toplevel | head -1
(2014年更新)正如Quentin Pradet所述,更新的Git子模块回购展示了一个简单的.git
文件,而不是.git
文件夹。
该.git
文件引用存储在父 repo .git/modules
子文件夹中的实际子模块git repo的路径。
(原始答案:2011年9月)
子模块的本质是用于作为子模块的git repo,它不知道它被父级仓库用作子模块。
一个肮脏的伎俩是:
git status --ignore-submodules=none
”如果您在git status
的结果中看到该文件,则您的回购应该是一个子模块。
如果它只是一个嵌套的repo,git status
应该完全忽略你的嵌套repo。
答案 1 :(得分:9)
这是一个shell函数,可用于检测:
function is_submodule()
{
(cd "$(git rev-parse --show-toplevel)/.." &&
git rev-parse --is-inside-work-tree) | grep -q true
}
修改以回应您提议的脚本:
看起来不错。
for line in $submodules; do cd "$parent_git/$line"; \
if [[ `pwd` = $_git_dir ]]; then return 0; fi; \
done
击> 因为它不会回来(所以只有第一个子模块才有效)
是匹配)。 我的版本检查而不更改目录;这可以通过cd
在子shell中完成,但返回exitcode会变得那么复杂
我不知道你从哪里得到$_git_dir
- 我用basename
(1)来得到它
信息(见下文)。
子模块中包含空格的问题也存在问题。 在我的版本中,子模块名称中的换行仍然存在问题,但我并不在意解决这个问题。 (注意'惯用'的方法是避免在子shell中使用while read
而不需要像readarray
这样的新bash-isms
最终声明所有vars本地修复了使用它时的潜在问题
在其他脚本中(例如,当外部脚本使用$path
变量时...)
我将_git_dir
重命名为top_level
(这不会引起混淆,因为GIT_DIR意味着其他内容)
我不知道git是否支持它(我不这么认为)但是如果子模块目录是符号链接,这个脚本可能会失败(因为“$ top_level / .. “可能会在包含存储库之外解析”
无法正确识别带有换行符的子模块名称
我还建议您捕获错误(使用'set -e','trap'返回1“ ERR'或类似的) - 不在我的脚本/练习阅读器
#!/bin/bash
function is_submodule() {
local top_level parent_git module_name path
# Find the root of this git repo, then check if its parent dir is also a repo
top_level="$(git rev-parse --show-toplevel)"
module_name="$(basename "$top_level")"
parent_git="$(cd "$top_level/.." && git rev-parse --show-toplevel 2> /dev/null)"
if [[ -n $parent_git ]]; then
# List all the submodule paths for the parent repo
while read path
do
if [[ "$path" != "$module_name" ]]; then continue; fi
if [[ -d "$top_level/../$path" ]]; then return 0; fi
done < <(cd $parent_git && git submodule --quiet foreach 'echo $path' 2> /dev/null)
#return 1
fi
return 1
}
if is_submodule; then
echo "In a submodule!"
else
echo "Not in a submodule"
fi
答案 2 :(得分:3)
我尝试了上面建议的脚本,但它对我不起作用。当然,我可能是世界上唯一一个子模块不是父模块的直接子模块的人。上面的代码假定它是。
然后显示父模型中的子模块路径也很好 - 我打算用它来显示一个bash shell提示符,告诉我我是否在子模块中,以及在哪里。
这是我的更新:
function is_submodule() {
local git_dir parent_git module_name path strip
# Find the root of this git repo, then check if its parent dir is also a repo
git_dir="$(git rev-parse --show-toplevel)"
parent_git="$(cd "$git_dir/.." && git rev-parse --show-toplevel 2> /dev/null)"
if [[ -n $parent_git ]]; then
strip=$((${#parent_git} + 1))
module_name=${git_dir:$strip}
# List all the submodule paths for the parent repo
while read path
do
if [[ "$path" != "$module_name" ]]; then continue; fi
if [[ -d "$parent_git/$path" ]]; then
echo $module_name
return 0;
fi
done < <(cd $parent_git && git submodule --quiet foreach 'echo $path' 2> /dev/null)
fi
return 1
}
# Usage
submodule=$(is_submodule)
if [[ $? -eq 0 ]]; then
echo "In a submodule! $submodule"
else
echo "Not in a submodule"
fi
答案 3 :(得分:3)
尝试git rev-parse --git-dir
当且仅当从项目根调用时才会返回".git"
:
if `git rev-parse --git-dir` == ".git"
// in root directory
else
// in submodule directory
除非您将$GIT_DIR
设置为该情况下的返回值(请参阅rev-parse):
- GIT-DIR
如果已定义,则显示$ GIT_DIR。否则显示.git目录的路径。显示的路径,相对时,相对于当前工作目录。
如果未定义$ GIT_DIR并且未检测到当前目录位于Git存储库或工作树中,则将消息打印到stderr并以非零状态退出。
答案 4 :(得分:1)
所选答案对于不在顶层的子模块不起作用。这样做也更简单:
function is_git_submodule() {
local module_name
module_path="$(git rev-parse --show-toplevel 2> /dev/null)"
# List all the submodule paths for the parent repo and look for our module's path
(cd "${module_path}/.." && git submodule --quiet foreach 'echo $toplevel/$path' 2> /dev/null) | \
grep --quiet --line-regexp --fixed-strings "$module_path"
}