如何确定我是否在git子模块中?

如何确定我是否在git子模块中?,git,shell,git-submodules,Git,Shell,Git Submodules,tldr;我如何才能发现我当前的工作目录在子模块目录中 如果在子模块内部或外部工作,工作过程会有所不同。我一次又一次地感到困惑,因为我不知道自己在子模块中 最理想的情况是_ugit_ps1会显示我在子模块中,但显然它没有这样做的规定 我想修补_ugit_ps1,向我展示我在子模块中的事实,但我找不到一种优雅的方式来查询git以了解这一事实 理想情况下,我希望有这样一个shell函数: function current_working_directory_is_in_a_submodule() {

tldr;我如何才能发现我当前的工作目录在子模块目录中

如果在子模块内部或外部工作,工作过程会有所不同。我一次又一次地感到困惑,因为我不知道自己在子模块中

最理想的情况是_ugit_ps1会显示我在子模块中,但显然它没有这样做的规定

我想修补_ugit_ps1,向我展示我在子模块中的事实,但我找不到一种优雅的方式来查询git以了解这一事实

理想情况下,我希望有这样一个shell函数:

function current_working_directory_is_in_a_submodule() {
  if some_magic; then
     echo "( $submodule_name )"
  else
     false
  fi
}

有什么神奇之处?

您可以查看.git目录。如果它实际上不是一个目录,你可以非常确定你在一个子模块中。至少在最新版本的git中,.git条目实际上是一个类似以下内容的文件:

gitdir: ../../../.git/modules/path/to/submodule
function current_working_directory_is_in_a_submodule() {
  submodule=$(git config core.worktree)
  if [ "$?" -eq 0 ]; then
     echo "( ${submodule##*/} )"
  else
     false
  fi
}
根据子模块的添加方式,它可能仍然有一个.git目录。有一个git子模块absorbgitdirs命令可以在父存储库中运行,它将解决这个问题;从git子模块手册页:

如果子模块的git目录位于子模块内,请将子模块的git目录移动到其superprojects$git_DIR/modules路径中,然后通过设置core.worktree并添加指向superprojects git目录中嵌入的git目录的.git文件来连接git目录及其工作目录

独立克隆并随后作为子模块或旧设置添加的存储库的子模块git目录位于子模块内,而不是嵌入到superprojects git目录中

默认情况下,此命令是递归的

…但这仍然有问题,因为当您位于子模块的根目录中时,测试很容易,而当您位于深度嵌套的目录中时,测试会更困难,因为这样您就必须迭代搜索父目录,直到找到.git目录或到达/

我上面引用的手册页条目为我们指出了第二个更好的选择:

在子模块中,core.worktree值设置为从子模块的根返回自身的相对路径。这意味着您可以a检查core.worktree设置是否有值来确定您是否在子模块中,b您可以使用core.worktree的值来确定子模块名称。这让我们感觉到:

gitdir: ../../../.git/modules/path/to/submodule
function current_working_directory_is_in_a_submodule() {
  submodule=$(git config core.worktree)
  if [ "$?" -eq 0 ]; then
     echo "( ${submodule##*/} )"
  else
     false
  fi
}
我不知道在其他情况下是否会自动设置core.worktree,但这在我有限的测试中似乎是可行的


如果当前存储库未被任何项目用作子模块,则不会输出任何内容。

子模块的可用性只是一个如何使用回购的问题,当前签出是否是其他签出认为应该存在的

您可以查看工作树是否位于另一个认为应该在此处进行签出的工作树中:

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

注意:这在Git2.13中是新的,在2.19.2中有一个小错误修复,如果超级项目有子模块合并冲突,它就会出错。通过在git存储库中为git运行git log-S show superproject working tree,然后检查所列修订的包含标记,可以找到信息。