Командная строка Git - знаете ли в подмодуле?

Есть ли способ в git узнать, находитесь ли вы в подмодуле? Вы можете думать, как git submodule foreach в родительском каталоге, но я не могу придумать общий способ показать, что вы находитесь в подмодуле, если вы в одном или в любом из дочерних каталогов внутри подмодуль.

Я думаю, вы могли бы найти корень репо с git rev-parse --show-toplevel, а затем cd-up level и снова найти корень этого репо, а затем сравнить список подмодулей с текущим каталогом, но это кажется таким липким...

Ответ 1

Вот функция оболочки, которую вы можете использовать для обнаружения:

function is_submodule() 
{       
     (cd "$(git rev-parse --show-toplevel)/.." && 
      git rev-parse --is-inside-work-tree) | grep -q true
}

Изменить В ответ на предложенный script:

Хорошо выглядит.

  • В

    есть ошибка.
    for line in $submodules; do cd "$parent_git/$line"; \
        if [[ `pwd` = $_git_dir ]]; then return 0; fi; \
    done
    

потому что он не будет возвращен cd (поэтому он будет работать только в том случае, если первый подмодуль является совпадением). Моя версия проверяется без изменения каталогов; Это можно сделать с помощью cd -ing в подоболочке, но возврат кода выхода становится сложным таким образом

  • Я не знаю, откуда вы получили $_git_dir from - я использовал basename (1), чтобы получить это (см. ниже).

  • Также существовала проблема с подмодулями, содержащими пробел в имени. В моей версии все еще есть проблема с новыми символами в именах подмодулей, но мне все равно, чтобы это исправить. (Обратите внимание на "идиоматический" способ избежать наличия while read в подоболочке без использования новых bash -ism вроде readarray)

  • наконец объявив, что все локаторы vars устраняют потенциальные проблемы при использовании этого внутри других скриптов (например, когда внешний script использует переменную $path...)

  • Я переименовал _git_dir в top_level (что менее запутанно, потому что GIT_DIR означает что-то еще)

Оставшиеся проблемы:

  • Я не знаю, поддерживает ли это git (я так не думаю), но этот script может выйти из строя, если каталог подмодуля является символической ссылкой (потому что "$ top_level/.." может разрешить вне содержащего репозитория)

  • имена подмодулей с символами новой строки не будут распознаны должным образом

  • Я также предлагаю вам ловушку ошибок (либо с 'set -e', 'trap' return 1 " ERR 'или аналогичный) - не в моем script/упражнении для чтения

#!/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

Ответ 2

(Обновление апреля 2017 года для Git 2.13, Q2 2017)

Теперь есть официальная команда, чтобы определить, является ли репо субмодулем родительского репо:

cd /path/to/potential/submodule/repo
git rev-parse --show-superproject-working-tree

См. commit bf0231c (08 марта 2017 г.) Стефан Беллер (stefanbeller).
(слияние Junio ​​C Hamano - gitster - в совершить 3edcc04, 17 марта 2017 г.

rev-parse: добавить --show-superproject-working-tree

В некоторых ситуациях полезно знать, является ли данный репозиторий является подмодулем другого репозитория.

Добавьте флаг --show-superproject-working-tree в git-rev-parse, чтобы было легко узнать, есть ли суперпроект.
Если суперпроект не существует, выход будет пустым.


(Обновление 2014). Как отметил Quentin Pradet, более поздние репозитории подмодуля Git показывают простой .git файл вместо папки .git. < ш > Этот файл .git ссылается на путь фактического субмодуля Git repo, хранящегося в подпапке parent repo .git/modules.


(Оригинальный ответ: сентябрь 2011 г.)

Сама природа подмодуля для репо Git, действующего как подмодуль, не имеет понятия, что он используется в качестве подмодуля родительским репо.

Один грязный трюк:

  • изменить файл
  • вернуться на один уровень выше текущего репо
  • попробуйте "git status --ignore-submodules=none"
  • восстановить измененный файл.

Если вы видите файл в результате git status, ваше репо должно быть подмодулем.
Если это всего лишь вложенное репо, git status должен полностью игнорировать ваше вложенное репо.

Ответ 3

Я попробовал предложенный выше script, и это не сработало для меня. Конечно, я могу быть единственным человеком в мире, у которого есть подмодуль, который не является прямым потомком родительского модуля. Вышеприведенный код предполагает, что он есть.

Также было бы полезно показать путь подмодуля внутри родителя - я планирую использовать это, чтобы показать приглашение оболочки bash, сообщающее мне, есть ли я в подмодуле и где.

Здесь мое обновление:

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

Ответ 4

попробуйте git rev-parse --git-dir, который вернет ".git" тогда и только тогда, когда вызывается из корня проекта:

if `git rev-parse --git-dir` == ".git"
    // in root directory
else
    // in submodule directory

если вы не установите $GIT_DIR, который будет возвращенным значением в этом случае (см. rev-parse):

- git -dir

Показывать $GIT_DIR, если они определены. В противном случае укажите путь к каталогу .git. Путь, показанный, когда относительный, относится к текущему рабочему каталогу.

Если $GIT_DIR не определен, и текущий каталог не обнаружен, чтобы лежать в репозитории Git или дереве работы, печатайте сообщение в stderr и выходите с ненулевым статусом.