Sprawdź, czy bieżący katalog to repozytorium Git


197

Piszę serię skryptów do zarządzania Git w Zsh.

Jak sprawdzić, czy bieżący katalog to repozytorium Git? (Gdy nie jestem w repozytorium Git, nie chcę wykonywać wielu poleceń i otrzymywać fatal: Not a git repositoryodpowiedzi).


Czy szukałeś inspiracji w pliku zakończenia bash (w contrib / dopełnienie / git-uzupełnianie.bash)? Używam polecenia __git_ps1 jako części mojego monitu bash. W rzeczywistości większość z nich będzie pochodzić z zsh. Funkcja __gitdir jest prawdopodobnie tą, której potrzebujesz.
jabbie

1
@jabbie: dlaczego nie udzielisz odpowiedzi?
amarillion

Czy sprawdziłeś już funkcje w dystrybucji zsh?
MBO


1
Uwaga: żaden z obecnych odpowiedzi rozważyć $GIT_DIRczy $GIT_WORK_TREEzmienne środowiskowe lub ich sposobu interakcji.
o11c

Odpowiedzi:


154

Skopiowane z pliku zakończenia bash, naiwny sposób to zrobić

# 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;

Możesz to zawinąć w funkcję lub użyć w skrypcie.

Skondensowane w jednym wierszu, odpowiednie dla bash i zsh

[ -d .git ] && echo .git || git rev-parse --git-dir > /dev/null 2>&1

3
@William Pursell Po co rozwidlać, kiedy nie trzeba? Głównie dla prędkości w trywialnym przypadku.
jabbie

16
Odpowiedź powinna zostać zaktualizowana w celu użycia git rev-parse --is-inside-git-dir. Osobiście używam git rev-parse --is-inside-work-treeprzed ustawieniem mojego PS1.
juliohm,

11
@juliohm --is-inside-git-dirzwróci true tylko wtedy, gdy faktycznie znajdujesz się w .gitkatalogu repozytorium. Nie sądzę, że OP tego szuka.
nyuszika7h

7
Ani --is-inside-work-treenie --is-inside-git-dirbędzie działać, gdy jesteś poza repozytorium git. patrz: groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
fisherwebdev

7
To się nie powiedzie, jeśli katalog git jest czymś innym niż .git. Aby uzyskać solidność, pomiń [ -d .git ]i po prostu użyj git rev-parse ....
Peter John Acklam,

134

Możesz użyć:

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

Które wypisze „prawda”, jeśli jesteś w drzewie roboczym repozytorium git.

Zauważ, że nadal zwraca dane wyjściowe do STDERR, jeśli jesteś poza repozytorium git (i nie wypisuje „fałszu”).

Zaczerpnięte z tej odpowiedzi: https://stackoverflow.com/a/2044714/12983


To najprostszy sposób, aby to sprawdzić.
calbertts

3
To nadal będzie wyświetlać fałsz dla nagiego repozytorium, które nie ma działającego drzewa
noggin182,

Nie dotyczy to podkatalogu. Muszę sprawdzić, czy git rev-parse --show-toplevelpasuje do podfolderu, który sprawdzam
oprócz

Wybrana odpowiedź nawet niczego nie wydrukowała. Ten zadziałał.
ScottyBlades

47

Użyj git rev-parse --git-dir

if git rev-parse --git-dir> / dev / null 2> & 1; następnie
  : # To jest poprawne repozytorium git (ale aktualnie działa
    # katalog może nie być najwyższym poziomem.
    # Sprawdź dane wyjściowe polecenia git rev-parsuj, jeśli cię to obchodzi)
jeszcze
  : # to nie jest repozytorium git
fi


7

Nie jestem pewien, czy istnieje publicznie dostępny / udokumentowany sposób wykonania tej czynności (istnieją pewne wewnętrzne funkcje git, których można używać / nadużywać w samym źródle git)

Możesz zrobić coś takiego;

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

7

Na podstawie odpowiedzi @Alex Cory :

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

nie zawiera żadnych zbędnych operacji i działa w -etrybie.

  • Jak zauważył @ go2null , nie będzie działać w nagim repo. Jeśli chcesz pracować z czystym repozytorium z jakiegokolwiek powodu, możesz po prostu sprawdzić, czy się git rev-parsepowiodło, ignorując jego wyniki.
    • Nie uważam tego za wadę, ponieważ powyższa linia jest przeznaczona do tworzenia skryptów i praktycznie wszystkie gitpolecenia są poprawne tylko w drzewie roboczym. Więc do celów skryptowych najprawdopodobniej jesteś zainteresowany nie tylko „repozytorium git”, ale także środowiskiem roboczym.

nie udaje się to w nagim repozytorium git
go2null

Zamiast sprawdzać dane wyjściowe, lepiej jest sprawdzić wartość zwracaną. W ogóle nie wzywaj [. Po prostu zrób if git rev-parse --is-inside-work-tree; then ...(z przekierowaniami zgodnie z życzeniem)
William Pursell

1
@WilliamPursell sprawdzanie wartości wyjścia nie działa tutaj: stackoverflow.com/questions/2180270/…
ivan_pozdeev

@Ivan_pozdeev Zależy od twojej definicji „pracy”. W takim przypadku powiedziałbym, że sprawdzanie wartości zwracanej działa, a sprawdzanie danych wyjściowych nie. W obu przypadkach, z punktu widzenia najlepszej praktyki pisania kodu w powłoce, bardziej odpowiednie jest sprawdzenie wartości zwracanej.
William Pursell,

@WilliamPursell, jeśli czytasz linkowany komentarz, wiedziałbyś, co mam na myśli przez „nie działa” tutaj.
ivan_pozdeev

6

Innym rozwiązaniem jest sprawdzenie kodu wyjścia polecenia.

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

Spowoduje to wydrukowanie 1, jeśli jesteś w folderze repozytorium git.


Zauważ, że będzie to miało wartość rc 0, nawet jeśli jesteś w .gitkatalogu - czego możesz chcieć lub nie.
ivan_pozdeev

Git napisany zdrowo więc można po prostu zamknąć pliki, których nie chcesz, git rev-parse 2>&-.
jthill

3

Ta odpowiedź przesyła próbkę funkcji POSIX powłoki i przykład użycia w celu uzupełnienia @ jabbie za odpowiedź .

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

gitzwraca poziom błędu, 0jeśli znajduje się w repozytorium git, w przeciwnym razie zwraca poziom błędu 128. (Zwraca również truelub falsejeśli znajduje się w repozytorium git.)

Przykład użycia

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

Niewystarczający. Wewnątrz .gitsię powiedzie, ale wydrukuj false.
ivan_pozdeev

@ivan_pozdeev: Jeśli git rev-parse --is-inside-work-treepowróci trueczy falseto jest wewnątrz repo git, i to, co funkcja zwraca. oznacza to, że funkcja jest poprawna
go2null

aby rozwinąć, zobacz opis w odpowiedzi, wartość zwracana z git jest ignorowana, używany jest poziom błędu.
go2null

2

to działa dla mnie. Nadal pojawiają się błędy, ale są one łatwe do stłumienia. działa również z podfolderów!

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

Możesz umieścić to w instrukcji if, jeśli chcesz warunkowo zrobić więcej.


2
Wystarczająco dobre w wielu przypadkach, ale nie udaje się to na zwykłym repozytorium git.
Wildcard,

3
git statusmoże być bardzo wolny na dużym / starym repo. Nie użyłbym tego do tego celu.
henrebotha

1

Dlaczego nie używać kodów wyjścia? Jeśli git repozytorium istnieje w bieżącym katalogu, to git branchi git tagpolecenia powrotu kod zakończenia 0; w przeciwnym razie zostanie zwrócony niezerowy kod wyjścia. W ten sposób możesz ustalić, czy repozytorium git istnieje, czy nie. Po prostu możesz uruchomić:

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

Zaleta : Flexibe. Działa zarówno dla nagich jak i nie nagich repozytoriów, a także w sh, zsh i bash.

Wyjaśnienie

  1. git tag: Pobieranie tagów repozytorium w celu ustalenia, czy istnieje, czy nie.
  2. > /dev/null 2>&1: Zapobieganie drukowaniu czegokolwiek, w tym wydruków normalnych i błędów.
  3. [ $? -eq 0 ]: Sprawdź, czy poprzednie polecenie zwróciło z kodem wyjścia 0, czy nie. Jak zapewne wiesz, każde niezerowe wyjście oznacza, że ​​stało się coś złego. $?dostaje kod zakończenia poprzedniego polecenia, i [, -eqi ]wykonać porównanie.

Na przykład możesz utworzyć plik o check-git-reponastępującej treści, ustawić go jako wykonywalny i uruchomić:

#!/bin/sh

if git tag > /dev/null 2>&1 && [ $? -eq 0 ]; then
    echo "Repository exists!";
else
    echo "No repository here.";
fi

0

# sprawdź, czy repozytorium git

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

To nie jest najlepsza praktyka. Jeśli zostanie uruchomiony poza katalogiem roboczym, otrzymasz „fatal: nie repozytorium git (lub którykolwiek z katalogów nadrzędnych): .git” zapisane na stderr, a „nie, nie jest repozytorium git” na stdout. W ogóle nie trzeba [tu przywoływać . Po prostu zrób:if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
William Pursell,

W moim przypadku czuję się z tym dobrze i chcę śledzić tę usterkę w moich logach. Twoje zdrowie!
Pascal Andy

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

Dziękuję ivan_pozdeev , Teraz mam test, jeśli w katalogu .git kod nie będzie działał, więc nie zostaną wydrukowane żadne błędy ani fałszywy status wyjścia.

Test „ ! [[$ (Pwd) = .git / || $ (pwd) = * .git]] ”, jeśli nie jesteś w repozytorium .git , uruchomi to polecenie git. Wbudowane polecenie typu służy do sprawdzania, czy masz zainstalowany git lub czy znajduje się on w ŚCIEŻCE. zobacz rodzaj pomocy


0

Co powiesz na to:

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

-1

Możesz dodać lub wymienić $ PS1 w swoim zshrc za pomocą jednego lub drugiego narzędzia git-prompt. W ten sposób możesz w wygodny sposób dowiedzieć się, czy jesteś w repozytorium git i czy stan repo jest w tym stanie.


3
Całe pytanie OP dotyczyło tego, jak to zrobić ze skryptu
Andrew C,

i jak nie można używać __git_ps1 z poziomu skryptu? Głównym celem git-prompt jest sprawdzenie statusu git bieżącego katalogu, o co pytano.
jxqz

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

The! neguje, więc nawet jeśli uruchomisz to w katalogu, który nie jest repozytorium git, nie spowoduje to poważnych błędów

> / Dev / null 2> & 1 wysyła wiadomości do / dev / null , ponieważ jesteś tylko po stanu wyjściowego. {} Jest do grup sterujących tak wszystkich poleceń Po zmianie || uruchomi się, jeśli git rev-parsowanie się powiedzie, ponieważ używamy! co negowało status wyjścia git rev-pars. Printf jest po prostu wydrukować jakiś stan wiadomości i git wydrukować status repo.

Zawiń go w funkcję lub umieść w skrypcie. Mam nadzieję że to pomoże


1
Niewystarczający. Wewnątrz .gitsię powiedzie, ale wydrukuj false.
ivan_pozdeev
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.