Перевірте, чи поточний каталог сховище Git


198

Я пишу серію сценаріїв для управління Git в zsh.

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


Ви подивилися файл набору файлів bash (в contrib / завершення / git-завершення.bash) для натхнення? Я використовую команду __git_ps1 як частину мого bash-рядка. Насправді більша частина буде джерелом у zsh. Функція __gitdir, мабуть, потрібна вам.
jabbie

1
@jabbie: чому ти не зробиш це відповідь?
amarillion

Ви перевірили функції вже в zsh-дистрибуції?
MBO


1
Примітка: жоден з поточних відповідей не враховує змінні середовища $GIT_DIRчи $GIT_WORK_TREEсередовища або спосіб їх взаємодії.
o11c

Відповіді:


154

Скопійовано з файлу завершення 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

3
@William Pursell Навіщо роздвоюватися, коли не потрібно? В основному для швидкості у тривіальному випадку.
jabbie

16
Відповідь слід оновити для використання git rev-parse --is-inside-git-dir. Я особисто використовую, git rev-parse --is-inside-work-treeперш ніж встановити PS1.
juliohm

12
@juliohm --is-inside-git-dirповерне значення true лише в тому випадку, якщо ви фактично знаходитесь в .gitкаталозі сховища. Я не думаю, що ОП цього шукає.
nyuszika7h

7
Ні, --is-inside-work-treeі не --is-inside-git-dirбуде працювати, коли ви знаходитесь поза межами git repo. дивіться: groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
fisherwebdev

7
Це не вдасться, якщо каталог git - це щось інше .git. Для надійності опустіть [ -d .git ]та просто використовуйте git rev-parse ....
Пітер Джон Аклам

134

Ви можете використовувати:

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

Що надрукує "true", якщо ви знаходитесь у робочому дереві git repos.

Зауважте, що він все ще повертає висновок STDERR, якщо ви перебуваєте поза git repo (і не друкує "false").

Взяте з цієї відповіді: https://stackoverflow.com/a/2044714/12983


Це найпростіший спосіб перевірити це.
calbertts

3
Це все ще надрукує помилку для голого сховища, у якого немає робочого дерева
noggin182

Це не враховує підкаталог. Мені потрібно перевірити, чи git rev-parse --show-toplevelзбігаються підпапки, які я перевіряю
Альпер

Обрана відповідь навіть нічого не надрукувала. Цей працював.
ScottyBlades

48

Використовуйте git rev-parse --git-dir

якщо git rev-parse --git-dir> / dev / null 2> & 1; тоді
  : # Це дійсне сховище git (але поточне працює)
    # каталог може бути не найвищим рівнем.
    # Перевірте вихід команди git rev-синтаксичного аналізу, якщо вам важливо)
ще
  : # це не сховище 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


7

Не впевнений, чи існує загальнодоступний / задокументований спосіб зробити це (є деякі внутрішні функції git, які ви можете використовувати / зловживати в самому джерелі git)

Ви могли б зробити щось на кшталт;

if ! git ls-files >& /dev/null; then
  echo "not in git"
fi

7

На основі відповіді @Alex Cory :

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

не містить зайвих операцій і працює в -eрежимі.

  • Як зазначав @ go2null , це не вийде в голому репо. Якщо ви хочете працювати з голим репо з будь-якої причини, ви можете просто перевірити на git rev-parseуспіх, ігноруючи його результат.
    • Я не вважаю це недоліком, оскільки наведений вище рядок призначений для сценаріїв, і практично всі gitкоманди дійсні лише у робочому дереві. Тож для створення сценаріїв ви, швидше за все, зацікавлені в тому, щоб бути не просто в "git repo", а всередині робочого дерева.

це не вдається всередині голого git repo
go2null

Замість того, щоб перевірити вихід, краще перевірити повернене значення. Не звертайтеся [взагалі. Просто зробіть if git rev-parse --is-inside-work-tree; then ...(з перенаправленнями за бажанням)
Вільям Перселл

1
@WilliamPursell перевірки значення виходу тут не працює: stackoverflow.com/questions/2180270 / ...
ivan_pozdeev

@Ivan_pozdeev Залежить від вашого визначення поняття "робота". У цьому випадку я б сказав, що перевірка повернутого значення працює, а перевірка виходу - не. У будь-якому випадку, з точки зору найкращої практики написання коду в оболонці, більш доцільно перевірити повернене значення.
Вільям Перселл

@WilliamPursell якщо ви прочитаєте пов'язаний коментар, ви б знали, що я тут маю на увазі під "не працює".
ivan_pozdeev

6

Ще одне рішення - перевірити код виходу команди.

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

Це буде надруковано 1, якщо ви знаходитесь у папці сховища git.


Зауважте, що це буде rc 0, навіть якщо ви знаходитесь в .gitкаталозі - чого ви можете, а може і не хочете.
ivan_pozdeev

Git, написані здраво так що ви можете просто закрити файли , які ви не хочете, git rev-parse 2>&-.
jthill

3

Ця відповідь дає приклад функції 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

Недостатньо. Всередині .gitце вдасться, але друкується false.
ivan_pozdeev

@ivan_pozdeev: Якщо git rev-parse --is-inside-work-treeповертається trueабо falseто є всередині мерзотника репо, і це те , що функція повертає. тобто функція правильна
go2null

щоб розгорнути, див. опис у відповіді, значення, повернене з git, ігнорується, рівень помилок - це те, що використовується.
go2null

2

це працює для мене. Ви все одно отримуєте помилки, але їх досить легко придушити. він також працює з підпапок!

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

Ви можете помістити це в оператор if if if, якщо вам потрібно умовно зробити більше.


2
Можливо, досить добре для багатьох випадків, але це не вдається на голому репо.
Wildcard

3
git statusможе бути дуже повільним на великому / старому репо. Я б не використовував це для цієї мети.
henrebotha

1

Чому б не використовувати вихідні коди? Якщо сховище git існує в поточному каталозі, тоді 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

0

# перевірити, чи 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

Це не найкраща практика. Якщо працювати за межами робочого каталогу, ви отримаєте "fatal: не git сховище (або будь-який з батьківських каталогів): .git", написане на stderr, і "ні, не git repo" в stdout. Тут взагалі не потрібно посилатися [. Просто зробіть:if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
Вільям Перселл

У моєму випадку мені це зручно, і я хочу відслідковувати цю проблему в своїх журналах. Ура!
Паскаль Енді

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 repo, тоді він запустить команду git. Команда вбудованого типу використовується для перевірки, чи встановлений у вас git чи він знаходиться у вашому PATH. див. тип довідки


0

Як про це:

if git status -s 2>/dev/null;then
    echo "this is a git repo"
else
    echo "this is NOT a git repo"
fi

-1

Ви можете додати або замінити $ PS1 в вашому zshrc з однієї або іншої GIT-підказки інструментів. Таким чином, ви можете зручно ознайомитись з тим, чи перебуваєте ви в git repo та про стан репо.


3
Все питання ОП полягало в тому, як це зробити за сценарієм
Ендрю С

і як можна використовувати __git_ps1 зсередини сценарію? Вся суть git-prompt полягає в тому, щоб перевірити стан git поточного каталогу, саме про це було запропоновано.
jxqz

-1
! git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { 
  printf '%s\n\n' "GIT repository detected." && git status
}

The! заперечує, навіть якщо ви запускаєте це в каталозі, який не є git repo, це не дасть вам фатальних помилок

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

Загорніть його у функцію або помістіть у сценарій. Сподіваюся, це допомагає


1
Недостатньо. Всередині .gitце вдасться, але друкується false.
ivan_pozdeev
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.