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

时间:2019-11-24 12:23:58

标签: git shell git-submodules

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是什么?

3 个答案:

答案 0 :(得分:2)

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

gitdir: ../../../.git/modules/path/to/submodule

根据子模块的添加方式,它可能仍具有一个.git目录。可以在父存储库中运行git submodule absorbgitdirs命令来解决此问题;来自git submodule手册页:

  

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

     

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

     

此命令默认是递归的。

...但是这仍然是有问题的,因为虽然在子模块的根目录中测试很容易,但是在深度嵌套的目录中则更困难(因为这样一来,您必须迭代搜索父级目录,直到找到.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,但这在我有限的测试中似乎可行。

答案 1 :(得分:2)

git rev-parse --show-superproject-working-tree

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

答案 2 :(得分:2)

Submodule-ness只是一个问题,即回购协议的使用方式,当前结帐是否是其他结帐所认为的内容。

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

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