我怎样才能知道我是否在 git 子模块中?
how can I find out if I'm inside a git submodule?
tldr;我怎样才能知道我当前的工作目录在子模块目录中?
如果在子模块内部或外部工作,工作流程会有所不同。我一次又一次地感到困惑,因为我不知道我在一个子模块中。
最好 __git_ps1
会告诉我我在子模块中,但显然它没有这样做的规定。
我想修补 __git_ps1
以显示我在子模块中的事实,但我找不到查询 git 的优雅方式。
理想情况下,我希望有一个像这样的 shell 函数:
function current_working_directory_is_in_a_submodule() {
if some_magic; then
echo "( $submodule_name )"
else
false
fi
}
什么是 some_magic
?
您可以查看 .git
目录。如果它 而不是 实际上是一个目录,你可以很确定你在一个子模块中。至少对于 git 的最新版本,.git
条目实际上是一个类似于以下内容的文件:
gitdir: ../../../.git/modules/path/to/submodule
根据子模块的添加方式,它可能仍然有一个 .git
目录。父存储库中有一个 git submodule absorbgitdirs
命令可以 运行 来解决这个问题;来自 git submodule
手册页:
If a git directory of a submodule is inside the submodule, move the git directory of the submodule into its superprojects $GIT_DIR/modules path and then connect the git directory and its working directory by setting the core.worktree and adding a .git file pointing to the git directory embedded in the superprojects git directory.
A repository that was cloned independently and later added as a submodule or old setups have the submodules git directory inside the submodule instead of embedded into the superprojects git directory.
This command is recursive by default.
...但这仍然是有问题的,因为虽然在子模块的根目录中测试很容易,但在深度嵌套的目录中时就更难了(因为那时你将不得不迭代搜索父目录,直到找到 .git
目录或到达 /
).
我上面引用的手册页条目为我们指出了第二个更好的选择:
在子模块中,设置了 core.worktree
值(从子模块的根返回到自身的相对路径)。这意味着您可以 (a) 检查 core.worktree
设置是否具有确定您是否在子模块中的值,以及 (b) 您可以使用 core.worktree
的值来确定子模块姓名。这让我们得到类似的东西:
function current_working_directory_is_in_a_submodule() {
submodule=$(git config core.worktree)
if [ "$?" -eq 0 ]; then
echo "( ${submodule##*/} )"
else
false
fi
}
不知道还有没有其他情况会自动设置core.worktree
,不过在我有限的测试中好像是这样。
git rev-parse --show-superproject-working-tree
如果当前存储库未被任何项目用作子模块,则不输出任何内容。
子模块性只是一个关于如何使用 repo 的问题,当前的结帐是否是其他结帐认为应该存在的。
您可以在此处查看工作树是否在另一个认为应该结帐的工作树中:
top=`git rev-parse --show-toplevel 2>&-` || exit
if up=`git -C "$top/.." rev-parse --show-toplevel 2>&-`
then echo work tree is at ${top#$up/} in another work tree
at=`git -C "$up" rev-parse :${top#$up/}` && echo ... which thinks $(git cat-file -t $at) $at should be checked out there
fi
tldr;我怎样才能知道我当前的工作目录在子模块目录中?
如果在子模块内部或外部工作,工作流程会有所不同。我一次又一次地感到困惑,因为我不知道我在一个子模块中。
最好 __git_ps1
会告诉我我在子模块中,但显然它没有这样做的规定。
我想修补 __git_ps1
以显示我在子模块中的事实,但我找不到查询 git 的优雅方式。
理想情况下,我希望有一个像这样的 shell 函数:
function current_working_directory_is_in_a_submodule() {
if some_magic; then
echo "( $submodule_name )"
else
false
fi
}
什么是 some_magic
?
您可以查看 .git
目录。如果它 而不是 实际上是一个目录,你可以很确定你在一个子模块中。至少对于 git 的最新版本,.git
条目实际上是一个类似于以下内容的文件:
gitdir: ../../../.git/modules/path/to/submodule
根据子模块的添加方式,它可能仍然有一个 .git
目录。父存储库中有一个 git submodule absorbgitdirs
命令可以 运行 来解决这个问题;来自 git submodule
手册页:
If a git directory of a submodule is inside the submodule, move the git directory of the submodule into its superprojects $GIT_DIR/modules path and then connect the git directory and its working directory by setting the core.worktree and adding a .git file pointing to the git directory embedded in the superprojects git directory.
A repository that was cloned independently and later added as a submodule or old setups have the submodules git directory inside the submodule instead of embedded into the superprojects git directory.
This command is recursive by default.
...但这仍然是有问题的,因为虽然在子模块的根目录中测试很容易,但在深度嵌套的目录中时就更难了(因为那时你将不得不迭代搜索父目录,直到找到 .git
目录或到达 /
).
我上面引用的手册页条目为我们指出了第二个更好的选择:
在子模块中,设置了 core.worktree
值(从子模块的根返回到自身的相对路径)。这意味着您可以 (a) 检查 core.worktree
设置是否具有确定您是否在子模块中的值,以及 (b) 您可以使用 core.worktree
的值来确定子模块姓名。这让我们得到类似的东西:
function current_working_directory_is_in_a_submodule() {
submodule=$(git config core.worktree)
if [ "$?" -eq 0 ]; then
echo "( ${submodule##*/} )"
else
false
fi
}
不知道还有没有其他情况会自动设置core.worktree
,不过在我有限的测试中好像是这样。
git rev-parse --show-superproject-working-tree
如果当前存储库未被任何项目用作子模块,则不输出任何内容。
子模块性只是一个关于如何使用 repo 的问题,当前的结帐是否是其他结帐认为应该存在的。
您可以在此处查看工作树是否在另一个认为应该结帐的工作树中:
top=`git rev-parse --show-toplevel 2>&-` || exit
if up=`git -C "$top/.." rev-parse --show-toplevel 2>&-`
then echo work tree is at ${top#$up/} in another work tree
at=`git -C "$up" rev-parse :${top#$up/}` && echo ... which thinks $(git cat-file -t $at) $at should be checked out there
fi