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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:44:32  来源:igfitidea点击:

Git command line - know if in submodule?

gitbashcommand-promptgit-submodules

提问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 in

    for 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 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 readin 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 $pathvariable...)

  • I renamed _git_dirto top_level(which is less confusing, because GIT_DIR means something else)

  • 我不知道你$_git_dir从哪里得到的 - 我用basename(1) 来获取这些信息(见下文)。

  • 名称中包含空格的子模块也存在问题。在我的版本中,子模块名称中的换行符仍然存在问题,但我不太关心解决这个问题。(注意避免while read在不需要新的 bash-ism 的情况下将放在子shell 中的“惯用”方法readarray

  • 最后声明所有本地变量修复在其他脚本中使用它时的潜在问题(例如,当外部脚本使用$path变量时......)

  • 我重命名_git_dirtop_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 日)stefanbeller
gitster

rev-parse: add --show-superproject-working-tree

In some situations it is useful to know if the given repository is a submodule of another repository.

Add the flag --show-superproject-working-treeto git-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-treegit-rev-parse方便查找是否存在超级项目。
当不存在超级项目时,输出将为空。

Jethro Yusuggests in the comments:

Jethro Yu在评论中建议:

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"
}