Is there any way in git to know if you're in a submodule? You can do thinks like git submodule foreach
in 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.
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...
Here is a shell function that you can use to detect this:
function is_submodule()
{
(cd "$(git rev-parse --show-toplevel)/.." &&
git rev-parse --is-inside-work-tree) | grep -q true
}
Edit In response to your proposed script:
Looking good.
There is a bug in
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
I don't know where you get $_git_dir
from - I used basename
(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 read
in a subshell without needing new bash-isms like readarray
)
finally declaring all the vars local fixes potential problems when using this
inside other scripts (e.g. when the outer script uses the $path
variable...)
I renamed _git_dir
to top_level
(which is less confusing, because GIT_DIR means something else)
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
#!/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