Compruebe si el directorio actual es un repositorio Git

197

Estoy escribiendo una serie de scripts para la gestión de Git en zsh.

¿Cómo verifico si el directorio actual es un repositorio Git? (Cuando no estoy en un repositorio de Git, no quiero ejecutar un montón de comandos y obtener un montón de fatal: Not a git repositoryrespuestas).

luego
fuente
¿Has mirado el archivo de finalización de bash (en contrib / completar / git-completar.bash) en busca de inspiración? Uso el comando __git_ps1 como parte de mi solicitud de bash. De hecho, la mayor parte se originará dentro de zsh. La función __gitdir es probablemente la que desea.
jabbie
1
@jabbie: ¿por qué no respondes eso?
amarillion
¿Ya ha verificado las funciones en la distribución zsh?
MBO
1
posible duplicado de Determinar si el directorio está bajo control git
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Nota: ninguna de las respuestas actuales consideran las $GIT_DIRo $GIT_WORK_TREEvariables de entorno, o la forma en que interactúan.
o11c

Respuestas:

154

Copiado del archivo de finalización de bash, la siguiente es una forma ingenua de hacerlo

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

Podrías envolverlo en una función o usarlo en un script.

Condensado en una condición de una línea adecuada para bash y zsh

[ -d .git ] && echo .git || git rev-parse --git-dir > /dev/null 2>&1
jabbie
fuente
3
@William Pursell ¿Por qué bifurcar cuando no es necesario? Principalmente por la velocidad en el caso trivial.
jabbie
16
La respuesta debe actualizarse para su uso git rev-parse --is-inside-git-dir. Yo personalmente uso git rev-parse --is-inside-work-treeantes de configurar mi PS1.
juliohm
11
@juliohm --is-inside-git-dirsolo devolverá verdadero si realmente está dentro del .gitdirectorio de un repositorio. No creo que el OP esté buscando eso.
nyuszika7h
77
Ni --is-inside-work-treetampoco --is-inside-git-dirva a funcionar cuando está fuera de un repositorio git. ver: groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
fisherwebdev
77
Esto fallará si el directorio git es diferente a .git. Para mayor robustez, omita el [ -d .git ]y solo use git rev-parse ....
Peter John Acklam
133

Puedes usar:

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

Lo cual imprimirá 'verdadero' si está en un árbol de trabajo de repositorios git.

Tenga en cuenta que aún devuelve la salida a STDERR si está fuera de un repositorio git (y no imprime 'falso').

Tomado de esta respuesta: https://stackoverflow.com/a/2044714/12983

TM.
fuente
Esta es la forma más simple de verificarlo.
calbertts
3
Esto todavía se imprimirá falso para un repositorio desnudo que no tiene árbol de trabajo
noggin182
Esto no considera el subdirectorio. Necesito verificar hace git rev-parse --show-toplevelpartidos con la subcarpeta estoy comprobando
Alper
La respuesta elegida ni siquiera imprimió nada. Este funcionó.
ScottyBlades
47

Utilice git rev-parse --git-dir

if git rev-parse --git-dir> / dev / null 2> & 1; luego
  : # Este es un repositorio git válido (pero el trabajo actual
    # directorio puede no ser el nivel superior.
    # Verifique la salida del comando git rev-parse si le importa)
más
  : # este no es un repositorio git
fi
William Pursell
fuente
7

No estoy seguro si hay una forma públicamente documentada de hacer esto (hay algunas funciones internas de git que puede usar / abusar en la fuente de git)

Podrías hacer algo como;

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

Basado en la respuesta de @Alex Cory :

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

no contiene operaciones redundantes y funciona en -emodo.

  • Como señaló @ go2null , esto no funcionará en un repositorio simple. Si desea trabajar con un repositorio desnudo por cualquier razón, puede verificar si tiene git rev-parseéxito, ignorando su salida.
    • No considero que esto sea un inconveniente porque la línea anterior está destinada a secuencias de comandos, y prácticamente todos los gitcomandos solo son válidos dentro de un árbol de trabajo. Entonces, para fines de secuencias de comandos, lo más probable es que esté interesado en estar no solo dentro de un "git repo" sino dentro de un árbol de trabajo.
ivan_pozdeev
fuente
esto falla dentro de un repositorio git desnudo
go2null
En lugar de verificar la salida, es mejor verificar el valor de retorno. No invocar [en absoluto. Solo hazlo if git rev-parse --is-inside-work-tree; then ...(con las redirecciones que desees)
William Pursell
1
@WilliamPursell comprobar el valor de salida no funciona aquí: stackoverflow.com/questions/2180270/…
ivan_pozdeev
@Ivan_pozdeev Depende de su definición de "trabajo". En este caso, diría que verificar el valor de retorno funciona, mientras que verificar la salida no. En cualquier caso, desde la perspectiva de las mejores prácticas para escribir código en el shell, es más apropiado verificar el valor de retorno.
William Pursell
@WilliamPursell si lees el comentario vinculado, sabrías lo que quiero decir con "no funciona" aquí.
ivan_pozdeev
6

Otra solución es verificar el código de salida del comando.

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

Esto imprimirá 1 si está en una carpeta de repositorio de git.


fuente
Tenga en cuenta que esto tendrá rc 0 incluso si está dentro del .gitdirectorio, lo que puede querer o no.
ivan_pozdeev
Git está escrito de manera sensata para que puedas cerrar archivos que no quieres git rev-parse 2>&-,.
jthill
3

Esta respuesta proporciona una función de shell POSIX de muestra y un ejemplo de uso para complementar la respuesta de @ jabbie .

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

gitdevuelve errorlevel 0si está dentro de un repositorio git, de lo contrario, devuelve errorlevel 128. (También regresa trueo falsesi está dentro de un repositorio git).

Ejemplo de uso

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
fuente
Insuficiente. En el interior .git, tendrá éxito pero imprime false.
ivan_pozdeev
@ivan_pozdeev: Si git rev-parse --is-inside-work-treevuelve trueo falseentonces es dentro de un repositorio git, y eso es lo que devuelve la función. es decir, la función es correcta
go2null
para expandir, vea la descripción en la respuesta, se ignora el valor devuelto por git, se usa el nivel de error.
go2null
2

esto funciona para mi Todavía obtienes los errores, pero son lo suficientemente fáciles de suprimir. ¡también funciona desde dentro de subcarpetas!

git status> / dev / null 2> & 1 && echo ¡Hola Mundo!

Puede poner esto en una declaración if then si necesita hacer más condicionalmente.

CharlesTWall3
fuente
2
Quizás sea lo suficientemente bueno para muchos casos, pero falla en un repositorio de git desnudo.
Comodín el
3
git statuspuede ser muy lento en un repositorio grande / antiguo. No lo usaría para este propósito.
henrebotha
1

¿Por qué no usar códigos de salida? Si existe un repositorio git en el directorio actual, a continuación, git branchy git taglos comandos de devolver el código de salida de 0; de lo contrario, se devolverá un código de salida distinto de cero. De esta manera, puede determinar si existe un repositorio git o no. Simplemente, puedes ejecutar:

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

Ventaja : Flexibe. Funciona para repositorios desnudos y no desnudos, y en sh, zsh y bash.

Explicación

  1. git tag: Obtener etiquetas del repositorio para determinar si existe o no.
  2. > /dev/null 2>&1: Evita imprimir cualquier cosa, incluidas las salidas normales y de error.
  3. [ $? -eq 0 ]: Verifique si el comando anterior regresó con el código de salida 0 o no. Como sabrá, cada salida distinta de cero significa que algo malo sucedió. $?recibe el código de salida de la orden anterior, y [, -eqy ]realizar la comparación.

Como ejemplo, puede crear un archivo check-git-repocon el siguiente contenido, hacerlo ejecutable y ejecutarlo:

#!/bin/sh

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

# comprobar si 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
Pascal Andy
fuente
Esta no es la mejor práctica. Si se ejecuta fuera de un directorio de trabajo, obtendrá "fatal: no es un repositorio git (o cualquiera de los directorios principales): .git" escrito en stderr, y "no, no es un repositorio git" en stdout. No hay necesidad de invocar [aquí en absoluto. Solo hazlo:if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
William Pursell
En mi caso, me siento cómodo con esto y quiero rastrear esta falla en mis registros. ¡Salud!
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

Gracias ivan_pozdeev , ahora tengo una prueba si dentro del directorio .git el código no se ejecutará, por lo que no se imprimen errores o el estado de salida es falso.

El " ! [[$ (Pwd) = .git / || $ (pwd) = * .git]] " prueba si no está dentro de un repositorio .git, entonces ejecutará el comando git. El comando de tipo incorporado se usa para verificar si tiene instalado git o si está dentro de su RUTA. ver tipo de ayuda

Jetchisel
fuente
0

¿Qué tal esto?

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

Puede agregar o reemplazar su $ PS1 en su zshrc con una u otra herramienta git-prompt. De esta manera, puede ser convenientemente informado de si está en un repositorio de git y del estado del repositorio.

jxqz
fuente
3
Toda la pregunta del OP fue cómo hacerlo desde un guión
Andrew C,
y ¿cómo no se puede usar __git_ps1 desde un script? El objetivo de git-prompt es verificar el estado de git del directorio actual, que es lo que se solicitó.
jxqz
-1
! git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { 
  printf '%s\n\n' "GIT repository detected." && git status
}

Los ! niega así que incluso si ejecuta esto en un directorio que no es un repositorio de git, no le dará algunos errores fatales

El > / dev / null 2> & 1 envía los mensajes a / dev / null ya que estás justo después del estado de salida. Los {} son para agrupaciones de comandos, por lo que todos los comandos después de || se ejecutará si el git rev-parse tuvo éxito ya que usamos a! que negó el estado de salida de git rev-parse. El printf es sólo para imprimir algún mensaje y git estado para imprimir el estado de la cesión temporal.

Envuélvalo en una función o póngalo en un script. Espero que esto ayude

Jetchisel
fuente
1
Insuficiente. En el interior .git, tendrá éxito pero imprime false.
ivan_pozdeev