Controlla se la directory corrente è un repository Git


199

Sto scrivendo una serie di script per la gestione di Git in zsh.

Come posso verificare se la directory corrente è un repository Git? (Quando non sono in un repository Git, non voglio eseguire un gruppo di comandi e ottenere un sacco di fatal: Not a git repositoryrisposte).


Hai dato un'occhiata al file di completamento bash (in contrib / completamento / git-completamento.bash) per avere l'ispirazione? Uso il comando __git_ps1 come parte del mio prompt di bash. In effetti, la maggior parte di esso proviene da zsh. La funzione __gitdir è probabilmente quella desiderata.
Jabbie,

1
@jabbie: perché non rispondi?
amarillion

Hai già controllato le funzioni nella distribuzione zsh?
MBO


1
Nota: nessuna delle risposte correnti considera le variabili $GIT_DIRo $GIT_WORK_TREEdell'ambiente o il modo in cui interagiscono.
o11c,

Risposte:


155

Copiato dal file di completamento bash, il seguente è un modo ingenuo per farlo

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

Puoi racchiuderlo in una funzione o utilizzarlo in uno script.

Condensato in una condizione di una riga adatta per bash e zsh

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

3
@William Pursell Perché fork quando non è necessario? Principalmente per la velocità nel caso banale.
Jabbie,

16
La risposta dovrebbe essere aggiornata per l'uso git rev-parse --is-inside-git-dir. Uso personalmente git rev-parse --is-inside-work-treeprima di impostare la mia PS1.
juliohm

12
@juliohm --is-inside-git-dirrestituirà true solo se ci si trova effettivamente nella .gitdirectory di un repository. Non credo che l'OP lo stia cercando.
nyuszika7h

7
--is-inside-work-tree--is-inside-git-dirfunzionerà quando ci si trova al di fuori di un repo git. vedi: groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
fisherwebdev

7
Questo fallirà se la directory git è qualcosa di diverso da .git. Per robustezza, ometti l' [ -d .git ]uso e basta git rev-parse ....
Peter John Acklam,

134

Puoi usare:

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

Che stamperà 'vero' se ci si trova in un albero di lavoro di repository git.

Si noti che restituisce comunque l'output a STDERR se si è al di fuori di un repository git (e non si stampa 'false').

Tratto da questa risposta: https://stackoverflow.com/a/2044714/12983


Questo è il modo più semplice per verificarlo.
calbertts,

3
Verrà comunque stampato falso per un repository nudo che non ha alberi funzionanti
noggin182,

Questo non considera la sottodirectory. Ho bisogno di verificare lo fa git rev-parse --show-toplevelpartite con la sottocartella Sto controllando
Alper

La risposta scelta non ha nemmeno stampato nulla. Questo ha funzionato.
ScottyBlades,

48

Usa git rev-parse --git-dir

se git rev-parse --git-dir> / dev / null 2> & 1; poi
  : # Questo è un repository git valido (ma l'attuale funziona
    # directory potrebbe non essere il livello principale.
    # Controlla l'output del comando git rev-parse se ti interessa)
altro
  : # questo non è un repository git
fi


7

Non sono sicuro che ci sia un modo pubblicamente accessibile / documentato per farlo (ci sono alcune funzioni git interne che puoi usare / abusare nella fonte git stessa)

Potresti fare qualcosa del genere;

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

7

Basato sulla risposta di @Alex Cory :

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

non contiene operazioni ridondanti e funziona in -emodalità.

  • Come notato da @ go2null , questo non funzionerà in un repository nudo. Se vuoi lavorare con un repository nudo per qualsiasi motivo, puoi semplicemente verificare la git rev-parseriuscita, ignorandone l'output.
    • Non lo considero uno svantaggio perché la riga sopra è destinata allo scripting e praticamente tutti i gitcomandi sono validi solo all'interno di un worktree. Quindi, ai fini dello scripting, molto probabilmente sei interessato a non essere solo all'interno di un "repository git" ma all'interno di un campo di lavoro.

questo fallisce all'interno di un repository bare git
go2null

Anziché controllare l'output, è consigliabile verificare il valore restituito. Non invocare [affatto. Fai if git rev-parse --is-inside-work-tree; then ...(con i reindirizzamenti come desideri).
William Pursell,

1
@WilliamPursell controllando il valore di uscita non funziona qui: stackoverflow.com/questions/2180270/...
ivan_pozdeev

@Ivan_pozdeev Dipende dalla tua definizione di "lavoro". In questo caso, direi che il controllo del valore restituito funziona, mentre il controllo dell'output no. In entrambi i casi, dal punto di vista delle migliori pratiche per la scrittura di codice nella shell, è più appropriato verificare il valore restituito.
William Pursell,

@WilliamPursell se leggi il commento collegato, sapresti cosa intendo per "non funziona" qui.
ivan_pozdeev

6

Un'altra soluzione è verificare il codice di uscita del comando.

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

Questo stamperà 1 se ti trovi in ​​una cartella del repository git.


Nota che questo avrà rc 0 anche se ti trovi all'interno della .gitdirectory, cosa che potresti o non vorrai.
ivan_pozdeev,

Git è scritto in modo sano in modo da poter file, proprio vicino che non si desidera, git rev-parse 2>&-.
jill

4

Questa risposta fornisce una funzione shell POSIX di esempio e un esempio di utilizzo per integrare la risposta di @ jabbie .

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

gitrestituisce errorlevel 0se si trova all'interno di un repository git, altrimenti restituisce errorlevel 128. (Restituisce anche trueo falsese si trova all'interno di un repository git.)

Esempio di utilizzo

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

Non sufficiente. All'interno .git, ci riuscirà ma stampa false.
ivan_pozdeev,

@ivan_pozdeev: se git rev-parse --is-inside-work-treeritorna trueo falseallora è all'interno di un repo git, e questo è ciò che la funzione restituisce. cioè, la funzione è corretta
go2null

per espandere, vedere la descrizione nella risposta, il valore restituito da git viene ignorato, il livello di errore è quello che viene utilizzato.
go2null

2

questo funziona per me. Ricevi ancora errori ma sono abbastanza facili da eliminare. funziona anche all'interno delle sottocartelle!

git status> / dev / null 2> & 1 && echo Ciao mondo!

Puoi inserirlo in un'istruzione if then se devi fare condizionalmente di più.


2
Abbastanza buono per molti casi forse, ma non riesce su un repository git nudo.
Wildcard il

3
git statuspuò essere molto lento su un repository grande / vecchio. Non lo userei per questo scopo.
henrebotha,

1

Perché non usare i codici di uscita? Se un repository git esiste nella directory corrente, quindi git branche git tagcomandi di ritorno codice di uscita 0; in caso contrario, verrà restituito un codice di uscita diverso da zero. In questo modo, puoi determinare se esiste o no un repository git. Semplicemente, puoi eseguire:

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

Vantaggio : Flexibe. Funziona sia per i repository nudi che per quelli non nudi, e in sh, zsh e bash.

Spiegazione

  1. git tag: Ottenere tag del repository per determinare se esiste o no.
  2. > /dev/null 2>&1: Impedisce di stampare qualsiasi cosa, inclusi output normali ed errori.
  3. [ $? -eq 0 ]: Controlla se il comando precedente ha restituito o meno il codice di uscita 0. Come forse saprai, ogni uscita diversa da zero significa che è successo qualcosa di brutto. $?ottiene il codice di uscita del comando precedente, e [, -eqe ]eseguire il confronto.

Ad esempio, è possibile creare un file denominato check-git-repocon i seguenti contenuti, renderlo eseguibile ed eseguirlo:

#!/bin/sh

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

0

# controlla se 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

Questa non è la migliore pratica. Se eseguito al di fuori di una directory di lavoro, otterrai "fatal: non un repository git (o una qualsiasi delle directory principali): .git" scritto su stderr e "no, non è un repository git" su stdout. Non è necessario invocare [affatto qui. Basta fare:if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
William Pursell il

Nel mio caso, mi sento a mio agio con questo e voglio tracciare questo problema tecnico nei miei registri. Saluti!
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

Grazie ivan_pozdeev , ora ho un test se all'interno della directory .git il codice non verrà eseguito, quindi nessun errore stampato o stato di uscita falso.

" ! [[$ (Pwd) = .git / || $ (pwd) = * .git]] " verifica se non sei all'interno di un repository .git, quindi eseguirà il comando git. Il comando di tipo incorporato viene utilizzato per verificare se git è installato o è all'interno del PERCORSO. vedi tipo di aiuto


0

A proposito di questo:

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

-1

Puoi aggiungere o sostituire $ PS1 in zshrc con uno o l' altro strumento git-prompt. In questo modo puoi essere facilmente informato se sei in un repository git e lo stato del repository è dentro.


3
L'intera domanda del PO era come farlo all'interno di una sceneggiatura
Andrew C,

e come __git_ps1 non può essere utilizzato all'interno di uno script? Il punto centrale di git-prompt è verificare lo stato git della directory corrente, che è ciò che è stato richiesto.
jxqz,

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

Il ! nega quindi anche se lo esegui in una directory che non è un repository git non ti darà alcuni errori fatali

Il > / dev / null 2> & 1 invia i messaggi a / dev / null visto che sei appena dopo lo stato di uscita. Il {} sono per gruppi di comando in modo che tutti i comandi dopo il || verrà eseguito se git rev-parse è riuscito poiché usiamo un! che ha negato lo stato di uscita di git rev-parse. Il printf è solo per stampare qualche messaggio e git stato per stampare lo stato del pronti contro termine.

Avvolgilo in una funzione o mettilo in uno script. Spero che questo ti aiuti


1
Non sufficiente. All'interno .git, ci riuscirà ma stampa false.
ivan_pozdeev,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.