bash Git 命令行 - 知道是否在子模块中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7359204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Git command line - know if in submodule?
提问by Andy Ray
Is there any way in git to know if you're in a submodule? You can do thinks like git submodule foreachin the parent directory but I can't seem to come up with a generic way to show that you're in a submodule if you're in one, or in any of the child directories inside the submodule.
在 git 中有什么方法可以知道您是否在子模块中?您可以像git submodule foreach在父目录中那样思考,但我似乎无法想出一种通用的方式来表明您在一个子模块中,如果您在一个子模块中,或者在子模块内的任何子目录中。
I guess you could find the repo root with git rev-parse --show-toplevel, and then cd-ing up a level, and finding the root of that repo again and then comparing the list of submodules to the current directory, but that seems so sticky...
我想你可以用 找到 repo 根目录git rev-parse --show-toplevel,然后 cd-ing 一个级别,再次找到该 repo 的根目录,然后将子模块列表与当前目录进行比较,但这似乎很粘......
采纳答案by sehe
Here is a shell function that you can use to detect this:
这是一个 shell 函数,您可以使用它来检测这个:
function is_submodule()
{
(cd "$(git rev-parse --show-toplevel)/.." &&
git rev-parse --is-inside-work-tree) | grep -q true
}
EditIn response to your proposed script:
编辑响应您提出的脚本:
Looking good.
看起来不错。
There is a bug infor line in $submodules; do cd "$parent_git/$line"; \ if [[ `pwd` = $_git_dir ]]; then return 0; fi; \ done
有一个错误for line in $submodules; do cd "$parent_git/$line"; \ if [[ `pwd` = $_git_dir ]]; then return 0; fi; \ done
because it won't cd back (so it would only work if the first submodule
is a match).My version checks without changing directories; That could be done done by cd-ing in a subshell, but returning the exitcode is getting complicated that way
因为它不会 cd 返回(所以它只有在第一个子模块匹配时才有效)。我的版本检查不改变目录;这可以通过cd在子 shell 中通过-ing来完成,但是返回退出代码会变得越来越复杂
I don't know where you get
$_git_dirfrom - I usedbasename(1) to get that information (see below).There was also a problem with submodules containing a space in the name. In my version, there is still a problem with newlines in submodule names left, but I don't care enough to fix that. (Note the 'idiomatic' way to avoid having the
while readin a subshell without needing new bash-isms likereadarray)finally declaring all the vars local fixes potential problems when using this inside other scripts (e.g. when the outer script uses the
$pathvariable...)I renamed
_git_dirtotop_level(which is less confusing, because GIT_DIR means something else)
我不知道你
$_git_dir从哪里得到的 - 我用basename(1) 来获取这些信息(见下文)。名称中包含空格的子模块也存在问题。在我的版本中,子模块名称中的换行符仍然存在问题,但我不太关心解决这个问题。(注意避免
while read在不需要新的 bash-ism 的情况下将放在子shell 中的“惯用”方法readarray)最后声明所有本地变量修复在其他脚本中使用它时的潜在问题(例如,当外部脚本使用
$path变量时......)我重命名
_git_dir为top_level(这不那么令人困惑,因为 GIT_DIR 意味着别的东西)
Remaining issues:
遗留问题:
I don't know whether git supports it (I don't think so) but this script could fail if the submodule directory is a symlink (because "$top_level/.." might resolve outside the containing repository)
submodule names with newlines will not be recognized properly
I also suggest you trap errors (either with 'set -e', 'trap "return 1" ERR' or similar) -- not in my script/exercise for reader
我不知道 git 是否支持它(我不这么认为)但是如果子模块目录是符号链接,这个脚本可能会失败(因为“$top_level/..”可能会在包含的存储库之外解析)
将无法正确识别带有换行符的子模块名称
我还建议您捕获错误(使用 'set -e'、'trap "return 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
}
Usage
用法
if is_submodule; then
echo "In a submodule!"
else
echo "Not in a submodule"
fi
回答by VonC
(Update April 2017 for Git 2.13, Q2 2017)
(2017 年 4 月更新 Git 2.13,2017 年第二季度)
There is now an official command to determine if a repo is a submodule of a parent repo:
现在有一个官方命令来确定一个 repo 是否是父 repo 的子模块:
cd /path/to/potential/submodule/repo
git rev-parse --show-superproject-working-tree
See commit bf0231c(08 Mar 2017) by Stefan Beller (stefanbeller).
(Merged by Junio C Hamano -- gitster--in commit 3edcc04, 17 Mar 2017)
请参阅Stefan Beller ( )提交的 bf0231c(2017 年 3 月 8 日)。(由Junio C Hamano合并-- --在3edcc04 提交中,2017 年 3 月 17 日)stefanbellergitster
rev-parse: add--show-superproject-working-treeIn some situations it is useful to know if the given repository is a submodule of another repository.
Add the flag
--show-superproject-working-treetogit-rev-parseto make it easy to find out if there is a superproject.
When no superproject exists, the output will be empty.
rev-parse: 添加--show-superproject-working-tree在某些情况下,了解给定存储库是否是另一个存储库的子模块很有用。
添加标志
--show-superproject-working-tree以git-rev-parse方便查找是否存在超级项目。
当不存在超级项目时,输出将为空。
Jethro Yusuggests in the comments:
get super project path regardless inside/outside of submodule:
git rev-parse --show-superproject-working-tree --show-toplevel | head -1
无论子模块的内部/外部,获取超级项目路径:
git rev-parse --show-superproject-working-tree --show-toplevel | head -1
(Update 2014) As noted by Quentin Pradet, more recent Git submodule repos show a simple .gitfileinstead of a .gitfolder.
That .gitfile reference the path of the actual submodule git repo, stored in the parentrepo .git/modulessubfolder.
(2014 年更新)正如Quentin Pradet所指出的,最近的 Git 子模块存储库显示了一个简单的.git文件而不是.git文件夹。
该.git文件引用了实际子模块 git repo 的路径,存储在父repo.git/modules子文件夹中。
(Original answer: Sept. 2011)
(原答案:2011 年 9 月)
The very nature of a submodule is for the git repo acting as submodule has no idea it is used as a submodule by a parent repo.
子模块的本质是作为子模块的 git 存储库不知道它被父存储库用作子模块。
One dirty trick would be to:
一个肮脏的伎俩是:
- change a file
- go back one level above the current repo
- try a "
git status --ignore-submodules=none" - restore the changed file.
- 更改文件
- 回到当前回购的上一层
- 试试“
git status --ignore-submodules=none” - 恢复更改的文件。
If you see the file in the result of the git status, your repo should be a submodule.
If it is only a nested repo, the git statusshould ignore your nested repo entirely.
如果您在 的结果中看到该文件,则git status您的 repo 应该是一个子模块。
如果它只是一个嵌套的 repo,则git status应该完全忽略您的嵌套 repo。
回答by amirnissim
try git rev-parse --git-dirwhich will return ".git"if and only if called from the project root:
try当且仅当从项目根调用时git rev-parse --git-dir才会返回".git":
if `git rev-parse --git-dir` == ".git"
// in root directory
else
// in submodule directory
unless you set $GIT_DIRwhich will be the returned value in that case (see rev-parse):
除非您设置$GIT_DIR在这种情况下哪个将成为返回值(请参阅rev-parse):
--git-dir
Show $GIT_DIR if defined. Otherwise show the path to the .git directory. The path shown, when relative, is relative to the current working directory.
If $GIT_DIR is not defined and the current directory is not detected to lie in a Git repository or work tree print a message to stderr and exit with nonzero status.
--git-dir
如果已定义,则显示 $GIT_DIR。否则显示 .git 目录的路径。显示的路径相对于当前工作目录。
如果未定义 $GIT_DIR 并且未检测到当前目录位于 Git 存储库或工作树中,则向 stderr 打印一条消息并以非零状态退出。
回答by Thomas Vander Stichele
I tried the script suggested above and it didn't work for me. Of course, I may be the only person in the world who has a submodule that's not a direct child of the parent module. The code above assumes that it is.
我尝试了上面建议的脚本,但它对我不起作用。当然,我可能是世界上唯一一个子模块不是父模块的直接子模块的人。上面的代码假设它是。
It would also be nice to then show the submodule path inside the parent - I plan to use this to show a bash shell prompt telling me if I'm in a submodule, and where.
然后在父模块中显示子模块路径也很好 - 我计划使用它来显示 bash shell 提示,告诉我我是否在子模块中以及在哪里。
Here's my update:
这是我的更新:
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
回答by Lexelby
The selected answer doesn't work for submodules that aren't at the top level. This does and is also simpler:
所选答案不适用于不在顶层的子模块。这确实而且也更简单:
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"
}

