Überprüfen Sie, ob das aktuelle Verzeichnis ein Git-Repository ist


197

Ich schreibe eine Reihe von Skripten für das Git-Management in zsh.

Wie überprüfe ich, ob das aktuelle Verzeichnis ein Git-Repository ist? (Wenn ich nicht in einem Git-Repo bin, möchte ich nicht eine Reihe von Befehlen ausführen und eine Reihe von fatal: Not a git repositoryAntworten erhalten).


Haben Sie sich die Bash-Abschlussdatei (in Contrib / Completion / Git-Completion.bash) als Inspiration angesehen? Ich verwende den Befehl __git_ps1 als Teil meiner Bash-Eingabeaufforderung. Tatsächlich wird das meiste davon innerhalb von zsh stammen. Die __gitdir-Funktion ist wahrscheinlich die gewünschte.
Jabbie

1
@jabbie: warum machst du das nicht zu einer antwort
Amarillion

Haben Sie Funktionen bereits in der zsh-Distribution überprüft?
MBO


1
Hinweis: Keine der aktuellen Antworten berücksichtigt die $GIT_DIRoder $GIT_WORK_TREEUmgebungsvariablen oder deren Interaktion.
o11c

Antworten:


154

Das Folgende ist eine naive Methode, die aus der Bash-Abschlussdatei kopiert wurde

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

Sie können dies entweder in eine Funktion einschließen oder in einem Skript verwenden.

In einem einzeiligen Zustand zusammengefasst, der für Bash und Zsh geeignet ist

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

3
@ William Pursell Warum gabeln, wenn Sie nicht brauchen? Hauptsächlich aus Gründen der Geschwindigkeit im Trivialfall.
Jabbie

16
Die Antwort sollte zur Verwendung aktualisiert werden git rev-parse --is-inside-git-dir. Ich persönlich benutze git rev-parse --is-inside-work-treevor dem Einstellen meiner PS1.
Juliohm

10
@juliohm --is-inside-git-dirgibt nur dann true zurück, wenn Sie sich tatsächlich im .gitVerzeichnis eines Repositorys befinden. Ich glaube nicht, dass das OP danach sucht.
Nyuszika7h

7
Weder --is-inside-work-treenoch --is-inside-git-dirfunktioniert es, wenn Sie sich außerhalb eines Git-Repo befinden. Siehe: groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
Fisherwebdev

7
Dies schlägt fehl, wenn das Git-Verzeichnis etwas anderes als ist .git. Lassen Sie aus Gründen der Robustheit das weg [ -d .git ]und verwenden Sie es einfach git rev-parse ....
Peter John Acklam

132

Sie können verwenden:

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

Was 'true' ausgibt, wenn Sie sich in einem Arbeitsbaum für Git-Repos befinden.

Beachten Sie, dass die Ausgabe weiterhin an STDERR zurückgegeben wird, wenn Sie sich außerhalb eines Git-Repos befinden (und nicht 'false' drucken).

Aus dieser Antwort entnommen: https://stackoverflow.com/a/2044714/12983


Dies ist der einfachste Weg, es auszuprobieren.
Calbertts

3
Dies wird immer noch false für ein nacktes Repository drucken, das keinen funktionierenden Baum hat
noggin182

Dies berücksichtigt nicht das Unterverzeichnis. Ich muss überprüfen, ob die git rev-parse --show-toplevelÜbereinstimmungen mit dem von mir überprüften Unterordner
übereinstimmen

Die gewählte Antwort druckte nicht einmal etwas aus. Dieser hat funktioniert.
ScottyBlades

47

Verwenden Sie git rev-parse --git-dir

if git rev-parse --git-dir> / dev / null 2> & 1; dann
  : # Dies ist ein gültiges Git-Repository (aber das aktuelle funktioniert
    # Verzeichnis ist möglicherweise nicht die oberste Ebene.
    # Überprüfen Sie die Ausgabe des Befehls git rev-parse, wenn Sie sich interessieren)
sonst
  : # Dies ist kein Git-Repository
fi


7

Ich bin mir nicht sicher, ob es eine öffentlich zugängliche / dokumentierte Möglichkeit gibt, dies zu tun (es gibt einige interne Git-Funktionen, die Sie in der Git-Quelle selbst verwenden / missbrauchen können).

Sie könnten so etwas tun;

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

7

Basierend auf der Antwort von @Alex Cory :

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

enthält keine redundanten Operationen und arbeitet im -eModus.

  • Wie @ go2null feststellte , funktioniert dies in einem nackten Repo nicht. Wenn Sie aus irgendeinem Grund mit einem Bare Repo arbeiten möchten, können Sie einfach überprüfen git rev-parse, ob dies erfolgreich ist, und die Ausgabe ignorieren.
    • Ich halte dies nicht für einen Nachteil, da die obige Zeile für die Skripterstellung vorgesehen ist und praktisch alle gitBefehle nur innerhalb eines Arbeitsbaums gültig sind. Für Skriptzwecke sind Sie höchstwahrscheinlich daran interessiert, nicht nur in einem "Git Repo", sondern auch in einem Arbeitsbaum zu sein.

Dies schlägt innerhalb eines nackten Git Repo
fehl

Anstatt die Ausgabe zu überprüfen, ist es besser, den Rückgabewert zu überprüfen. Rufen Sie überhaupt nicht auf [. Tun Sie es einfach if git rev-parse --is-inside-work-tree; then ...(mit Weiterleitungen wie gewünscht)
William Pursell

1
@ WilliamPursell Überprüfung des Exit-Werts funktioniert hier nicht: stackoverflow.com/questions/2180270/…
ivan_pozdeev

@Ivan_pozdeev Hängt von Ihrer Definition von "Arbeit" ab. In diesem Fall würde ich sagen, dass das Überprüfen des Rückgabewerts funktioniert, während das Überprüfen der Ausgabe nicht funktioniert. In beiden Fällen ist es aus Sicht der Best Practice für das Schreiben von Code in die Shell besser, den Rückgabewert zu überprüfen.
William Pursell

@WilliamPursell Wenn Sie den verlinkten Kommentar lesen, wissen Sie, was ich hier mit "funktioniert nicht" gemeint habe.
ivan_pozdeev

6

Eine andere Lösung besteht darin, nach dem Exit-Code des Befehls zu suchen.

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

Dies gibt 1 aus, wenn Sie sich in einem Git-Repository-Ordner befinden.


Beachten Sie, dass dies rc 0 hat, auch wenn Sie sich im .gitVerzeichnis befinden - was Sie vielleicht wollen oder nicht.
ivan_pozdeev

Git ist vernünftig geschrieben, so dass Sie einfach Dateien schließen können, die Sie nicht wollen git rev-parse 2>&-.
Bis zum

3

Diese Antwort enthält ein Beispiel für eine POSIX-Shell-Funktion und ein Verwendungsbeispiel zur Ergänzung der Antwort von @ jabbie .

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

gitGibt die Fehlerstufe zurück, 0wenn es sich in einem Git-Repository befindet 128. Andernfalls wird die Fehlerstufe zurückgegeben . (Es wird auch zurückgegeben trueoder falsewenn es sich in einem Git-Repository befindet.)

Anwendungsbeispiel

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

Nicht ausreichend. Im Inneren .gitwird es aber drucken gelingen false.
ivan_pozdeev

@ivan_pozdeev: Wenn git rev-parse --is-inside-work-treezurückgegeben wird trueoder falsedann befindet es sich in einem Git-Repo, und genau das gibt die Funktion zurück. Das heißt, die Funktion ist korrekt
go2null

Zum Erweitern siehe Beschreibung in der Antwort, der von git zurückgegebene Wert wird ignoriert, die Fehlerstufe wird verwendet.
go2null

2

das funktioniert bei mir. Sie erhalten immer noch die Fehler, aber sie sind leicht zu unterdrücken. Es funktioniert auch in Unterordnern!

Git-Status> / dev / null 2> & 1 && echo Hallo Welt!

Sie können dies in eine if then-Anweisung einfügen, wenn Sie bedingt mehr tun müssen.


2
Gut genug für viele Fälle vielleicht, aber es scheitert an einem nackten Git Repo.
Wildcard

3
git statuskann auf einem großen / alten Repo sehr langsam sein. Ich würde es nicht für diesen Zweck verwenden.
Henrebotha

1

Warum nicht Exit-Codes verwenden? Wenn im aktuellen Verzeichnis ein Git-Repository vorhanden ist, geben die Befehle git branchund den git tagExit-Code 0 zurück. Andernfalls wird ein Exit-Code ungleich Null zurückgegeben. Auf diese Weise können Sie feststellen, ob ein Git-Repository vorhanden ist oder nicht. Sie können einfach ausführen:

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

Vorteil : Flexibe. Es funktioniert sowohl für nackte als auch für nicht nackte Repositorys sowie in sh, zsh und bash.

Erläuterung

  1. git tag: Tags des Repositorys abrufen, um festzustellen, ob sie vorhanden sind oder nicht.
  2. > /dev/null 2>&1: Verhindern, dass etwas gedruckt wird, einschließlich normaler und Fehlerausgaben.
  3. [ $? -eq 0 ]: Überprüfen Sie, ob der vorherige Befehl mit dem Exit-Code 0 zurückgegeben wurde oder nicht. Wie Sie vielleicht wissen, bedeutet jeder Ausgang ungleich Null, dass etwas Schlimmes passiert ist. $?erhält den Beendigungscode des vorherigen Befehls, und [, -eqund ]den Vergleich durchzuführen.

Sie können beispielsweise eine Datei check-git-repomit dem folgenden Inhalt erstellen , sie ausführbar machen und ausführen:

#!/bin/sh

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

0

# Überprüfen Sie, ob 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

Dies ist keine bewährte Methode. Wenn Sie außerhalb eines Arbeitsverzeichnisses ausgeführt werden, erhalten Sie "fatal: kein Git-Repository (oder eines der übergeordneten Verzeichnisse): .git", geschrieben auf stderr, und "nein, ist kein Git-Repo" auf stdout. Hier muss überhaupt nichts aufgerufen [werden. Tun Sie einfach:if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
William Pursell

In meinem Fall fühle ich mich damit wohl und möchte diesen Fehler in meinen Protokollen nachverfolgen. Prost!
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

Vielen Dank ivan_pozdeev . Jetzt habe ich einen Test, ob der Code im Verzeichnis .git nicht ausgeführt wird, sodass keine Fehler ausgedruckt werden oder der Status falsch beendet wird.

Das " ! [[$ (Pwd) = .git / || $ (pwd) = * .git]] " testet, wenn Sie sich nicht in einem .git- Repo befinden, und führt den Befehl git aus. Mit dem integrierten Befehl type können Sie überprüfen, ob git installiert ist oder sich in Ihrem PATH befindet. siehe Hilfetyp


0

Wie wäre es damit:

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

-1

Sie können Ihre $ PS1 in Ihrem zshrc durch das eine oder andere git-prompt- Tool ergänzen oder ersetzen . Auf diese Weise können Sie bequem feststellen, ob Sie sich in einem Git-Repo befinden und in welchem ​​Zustand sich das Repo befindet.


3
Die gesamte Frage des OP war, wie man es aus einem Skript heraus macht
Andrew C

und wie kann __git_ps1 nicht aus einem Skript heraus verwendet werden? Der Sinn der Git-Eingabeaufforderung besteht darin, den Git-Status des aktuellen Verzeichnisses zu überprüfen, was gefragt wurde.
jxqz

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

Das ! negiert dies. Selbst wenn Sie dies in einem Verzeichnis ausführen, das kein Git-Repo ist, werden Ihnen keine schwerwiegenden Fehler angezeigt

Das > / dev / null 2> & 1 sendet die Nachrichten an / dev / null, da Sie sich gerade nach dem Exit-Status befinden. Die {} sind für Befehlsgruppierungen, also alle Befehle nach dem || wird ausgeführt, wenn die git rev-parse erfolgreich war, da wir a! was den Exit-Status von git rev-parse negierte. Der printf dient nur zum Drucken einer Nachricht und des Git-Status, um den Status des Repos zu drucken.

Wickeln Sie es in eine Funktion ein oder fügen Sie es in ein Skript ein. Hoffe das hilft


1
Nicht ausreichend. Im Inneren .gitwird es aber drucken gelingen false.
ivan_pozdeev
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.