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).

zaraz
źródło
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
możliwy duplikat Ustal, czy katalog jest pod kontrolą git
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
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 <[email protected]>
# 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
Jabbie
źródło
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

TM.
źródło
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
William Pursell
źródło
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
James
źródło
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.
ivan_pozdeev
źródło
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.


źródło
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
go2null
źródło
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.

CharlesTWall3
źródło
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
MAChitgarha
źródło
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
Pascal Andy
źródło
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

Jetchisel
źródło
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
SebMa
źródło
-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.

jxqz
źródło
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

Jetchisel
źródło
1
Niewystarczający. Wewnątrz .gitsię powiedzie, ale wydrukuj false.
ivan_pozdeev