Проверьте, является ли текущий каталог репозиторием Git

212

Я пишу серию скриптов для управления Git на zsh.

Как проверить, является ли текущий каталог репозиторием Git? (Когда я не использую репозиторий Git, я не хочу выполнять кучу команд и получать кучу fatal: Not a git repositoryответов).

анон
источник
Вы для вдохновения смотрели файл завершения bash (в contrib / Завершение / git-Completion.bash)? Я использую команду __git_ps1 как часть моей командной строки bash. Фактически, большая часть его будет исходить из zsh. Возможно, вам нужна функция __gitdir.
jabbie 01
2
@jabbie: почему бы тебе не дать ответ?
amarillion 01
Вы уже проверяли функции в дистрибутиве zsh?
MBO
1
возможный дубликат определения, находится ли каталог под контролем git
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Примечание: ни один из текущих ответов не учитывать $GIT_DIRили $GIT_WORK_TREEпеременные окружения, или как они взаимодействуют.
o11c

Ответы:

161

Скопировано из файла завершения bash, вот наивный способ сделать это

# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
# Distributed under the GNU General Public License, version 2.0.

if [ -d .git ]; then
  echo .git;
else
  git rev-parse --git-dir 2> /dev/null;
fi;

Вы можете заключить это в функцию или использовать в скрипте.

Сконцентрировано в однострочное условие, подходящее для bash и zsh

[ -d .git ] && echo .git || git rev-parse --git-dir > /dev/null 2>&1
Джабби
источник
4
@William Pursell Зачем форк, если он вам не нужен? В основном для скорости в тривиальном случае.
jabbie
19
Для использования ответ необходимо обновить git rev-parse --is-inside-git-dir. Я лично использую git rev-parse --is-inside-work-treeперед установкой PS1.
juliohm
14
@juliohm --is-inside-git-dirвернет true только в том случае, если вы действительно находитесь в .gitкаталоге репозитория. Я не думаю, что OP этого ищет.
nyuszika7h
8
Ни то, --is-inside-work-treeни другое не --is-inside-git-dirбудет работать, когда вы находитесь вне репозитория git. см. groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
fisherwebdev
10
Это не удастся, если каталог git отличается от .git. Для надежности опустите [ -d .git ]и просто используйте git rev-parse ....
Питер Джон Эклам
143

Ты можешь использовать:

git rev-parse --is-inside-work-tree

Что напечатает «истина», если вы находитесь в рабочем дереве репозиториев git.

Обратите внимание, что он по-прежнему возвращает вывод в STDERR, если вы находитесь за пределами репозитория git (и не печатает false).

Взято из этого ответа: https://stackoverflow.com/a/2044714/12983

TM.
источник
Это самый простой способ проверить это.
Calbertts
3
Это все равно будет выводить false для
пустого
Это не учитывает подкаталог. Мне нужно проверить, git rev-parse --show-toplevelсоответствует ли подпапка, которую я проверяю,
Альпер,
Выбранный ответ даже ничего не распечатал. Этот сработал.
ScottyBlades
50

Используйте git rev-parse --git-dir

если git rev-parse --git-dir> / dev / null 2> & 1; тогда
  : # Это действующий репозиторий git (но текущий рабочий
    # каталог не может быть верхнего уровня.
    # Проверьте вывод команды git rev-parse, если вам интересно)
еще
  : # это не репозиторий git
фи
Уильям Перселл
источник
27

Или вы можете сделать это:

inside_git_repo="$(git rev-parse --is-inside-work-tree 2>/dev/null)"

if [ "$inside_git_repo" ]; then
  echo "inside git repo"
else
  echo "not in git repo"
fi
Алекс Кори
источник
2
Мне нравится этот, потому что он тоже работает из подкаталога
joehanna
9

На основе ответа @Alex Cory :

[ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" == "true" ]

не содержит лишних операций и работает в -eрежиме.

  • Как отметил @ go2null , это не будет работать в чистом репо. Если по какой-то причине вы хотите работать с голым репо, вы можете просто проверить его git rev-parseуспешность, игнорируя его вывод.
    • Я не считаю это недостатком, потому что строка выше имеет отступ для сценариев, и практически все gitкоманды действительны только внутри рабочего дерева. Таким образом, для написания сценариев вам, скорее всего, будет интересно находиться не просто внутри «репозитория git», а внутри рабочего дерева.
ivan_pozdeev
источник
это не удается внутри
чистого репозитория
1
Вместо проверки вывода лучше проверять возвращаемое значение. Ни в коем случае не призывайте [. Просто делайте if git rev-parse --is-inside-work-tree; then ...(с перенаправлением по желанию)
Уильям Перселл,
1
@WilliamPursell проверка значения выхода здесь не работает: stackoverflow.com/questions/2180270/…
ivan_pozdeev
@Ivan_pozdeev Зависит от вашего определения слова «работа». В этом случае я бы сказал, что проверка возвращаемого значения работает, а проверка вывода - нет. В любом случае, с точки зрения передовой практики написания кода в оболочке, более целесообразно проверить возвращаемое значение.
Уильям Перселл
@WilliamPursell, если вы прочитаете связанный комментарий, вы поймете, что я имел в виду под словом «не работает» здесь.
ivan_pozdeev 07
8

Не уверен, есть ли общедоступный / документированный способ сделать это (есть некоторые внутренние функции git, которые вы можете использовать / злоупотреблять в самом источнике git)

Вы могли бы сделать что-то вроде:

if ! git ls-files >& /dev/null; then
  echo "not in git"
fi
Джеймс
источник
6

Другое решение - проверить код выхода команды.

git rev-parse 2> /dev/null; [ $? == 0 ] && echo 1

Это напечатает 1, если вы находитесь в папке репозитория git.


источник
Обратите внимание, что здесь будет rc 0, даже если вы находитесь внутри .gitкаталога, что может вам понадобиться, а может и нет.
ivan_pozdeev
1
Git, написанные здраво так что вы можете просто закрыть файлы , которые вы не хотите, git rev-parse 2>&-.
jth 03
4

Этот ответ предоставляет образец функции оболочки POSIX и пример использования, дополняющий ответ @ jabbie .

is_inside_git_repo() {
    git rev-parse --is-inside-work-tree >/dev/null 2>&1
}

gitвозвращает errorlevel, 0если он находится внутри репозитория git, иначе он возвращает errorlevel 128. (Он также возвращается trueили falseнаходится в репозитории git.)

Пример использования

for repo in *; do
    # skip files
    [ -d "$repo" ] || continue
    # run commands in subshell so each loop starts in the current dir
    (
        cd "$repo"
        # skip plain directories
        is_inside_git_repo || continue
        printf '== %s ==\n' "$repo"
        git remote update --prune 'origin' # example command
        # other commands here
    )
done
go2null
источник
Не достаточно. Внутри .gitполучится, но распечатать false.
ivan_pozdeev
@ivan_pozdeev: Если git rev-parse --is-inside-work-treeвозвращается, trueили falseтогда он находится внутри репозитория git, и это то, что возвращает функция. то есть функция правильная
go2null
Чтобы развернуть, см. описание в ответе, значение, возвращаемое из git, игнорируется, используется уровень ошибки.
go2null
2

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

git status> / dev / null 2> & 1 && echo Hello World!

Вы можете поместить это в оператор if then, если вам нужно условно сделать больше.

CharlesTWall3
источник
2
Возможно, достаточно для многих случаев, но не работает на голом репозитории git.
Wildcard
3
git statusможет быть очень медленным на большом / старом репо. Я бы не стал использовать его для этой цели.
henrebotha
2

# проверяем, есть ли git repo

if [ $(git rev-parse --is-inside-work-tree) = true ]; then
    echo "yes, is a git repo"
    git pull
else
    echo "no, is not a git repo"
    git clone url --depth 1
fi
Паскаль Энди
источник
1
Это не лучшая практика. При запуске вне рабочего каталога вы получите «fatal: not a git repository (или любой из родительских каталогов): .git», написанное на stderr, и «no, is not a git repo» на stdout. Здесь вообще нет необходимости призывать [. Просто сделайте:if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
Уильям Перселл
В моем случае меня это устраивает, и я хочу отслеживать этот сбой в своих журналах. Ура!
Паскаль Энди
1

Почему бы не использовать коды выхода? Если мерзавец хранилище существует в текущем каталоге, а затем git branchи git tagкоманды возвращают код выхода на 0; в противном случае будет возвращен ненулевой код выхода. Таким образом, вы можете определить, существует ли репозиторий git или нет. Просто вы можете запустить:

git tag > /dev/null 2>&1 && [ $? -eq 0 ]

Преимущество : Flexibe. Он работает как с голыми, так и с обычными репозиториями, а также с sh, zsh и bash.

Объяснение

  1. git tag: Получение тегов репозитория, чтобы определить, существует он или нет.
  2. > /dev/null 2>&1: Предотвращение печати чего-либо, включая нормальный вывод и вывод ошибок.
  3. [ $? -eq 0 ]: Проверить, вернула ли предыдущая команда код выхода 0 или нет. Как вы, наверное, знаете, каждый ненулевой выход означает, что произошло что-то плохое. $?получает код выхода предыдущей команды, и [, -eqи ]выполняет сравнение.

Например, вы можете создать файл check-git-repoсо следующим содержимым, сделать его исполняемым и запустить:

#!/bin/sh

if git tag > /dev/null 2>&1 && [ $? -eq 0 ]; then
    echo "Repository exists!";
else
    echo "No repository here.";
fi
MAChitgarha
источник
0
if ! [[ $(pwd) = *.git/* || $(pwd) = *.git ]]; then 
  if type -P git >/dev/null; then
    ! git rev-parse --is-inside-work-tree >/dev/null 2>&1 || {
     printf '\n%s\n\n' "GIT repository detected." && git status
    }
  fi
fi

Спасибо ivan_pozdeev , теперь у меня есть тест, если внутри каталога .git код не запускается, поэтому ошибки не распечатываются или статус ложного выхода.

Команда " ! [[$ (Pwd) = .git / || $ (pwd) = * .git]] " проверяет, не находитесь ли вы внутри репозитория .git, тогда он выполнит команду git. Команда встроенного типа используется для проверки того, установлен ли у вас git или он находится в вашем PATH. см. тип помощи

Jetchisel
источник
-1

Вы можете добавить или заменить свой $ PS1 в zshrc с помощью тех или иных инструментов git-prompt. Таким образом, вы можете удобно узнать, находитесь ли вы в репозитории git и находится ли оно в состоянии.

jxqz
источник
3
Весь вопрос OP заключался в том, как это сделать из сценария
Эндрю Си
и как можно не использовать __git_ps1 из сценария? Вся суть git-prompt заключается в проверке статуса git текущего каталога, о чем и просили.
jxqz
__git_ps1 имеет множество функций, таких как необязательные проверки состояния и цвета терминала - все, что вам нужно, это фактическая базовая команда, которую он использует для любой информации о состоянии, которую вы хотите, а OP только спрашивал о нахождении внутри рабочего дерева. По сути, вы пытаетесь использовать бульдозер, чтобы заменить лампочку.
Томас Гайо-Сионнест,
-1
! git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { 
  printf '%s\n\n' "GIT repository detected." && git status
}

! отрицает, поэтому даже если вы запустите это в каталоге, который не является репозиторием git, он не даст вам фатальных ошибок

> / DEV / нуль 2> & 1 отправляет сообщения / DEV / нуль , так как вы только после того, как статус выхода. {} Предназначены для командных группировок так что все команды после того , как || запустится, если git rev-parse завершился успешно, поскольку мы используем! что отменяет статус выхода git rev-parse. Printf просто напечатать некоторые сообщения и GIT статус для печати статус репо.

Оберните его в функцию или поместите в сценарий. Надеюсь это поможет

Jetchisel
источник
1
Не достаточно. Внутри .gitвсе получится, но распечатать false.
ivan_pozdeev