Verifique se o diretório atual é um repositório Git

197

Estou escrevendo uma série de scripts para gerenciamento de Git no zsh.

Como verifico se o diretório atual é um repositório Git? (Quando não estou em um repositório Git, não quero executar vários comandos e obter várias fatal: Not a git repositoryrespostas).

anon
fonte
Você já consultou o arquivo de conclusão do bash (em contrib / completation / git-conclusão.bash) para obter inspiração? Eu uso o comando __git_ps1 como parte do meu prompt do bash. De fato, a maior parte dele será originada no zsh. A função __gitdir é provavelmente a que você deseja.
Jabbie
1
@ jabbie: por que você não faz disso uma resposta?
amarillion
Você já verificou funções na distribuição zsh?
MBO 04/02
1
possível duplicata de determinar se o diretório está sob controle git
Ciro Santilli郝海东冠状病六四事件法轮功
1
Nota: nenhuma das respostas atuais considerar as $GIT_DIRou $GIT_WORK_TREEvariáveis de ambiente, ou como eles interagem.
o11c 17/12/19

Respostas:

154

Copiado do arquivo de conclusão do bash, a seguir é uma maneira ingênua de fazer isso

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

Você pode agrupar isso em uma função ou usá-lo em um script.

Condensado em uma condição de uma linha adequada para bash e zsh

[ -d .git ] && echo .git || git rev-parse --git-dir > /dev/null 2>&1
jabbie
fonte
3
@William Pursell Por que bifurcar quando você não precisa? Principalmente pela velocidade no caso trivial.
Jbbie
16
A resposta deve ser atualizada para uso git rev-parse --is-inside-git-dir. Eu pessoalmente uso git rev-parse --is-inside-work-treeantes de definir meu PS1.
precisa saber é
11
O @juliohm --is-inside-git-dirretornará true somente se você estiver realmente dentro do .gitdiretório de um repositório. Não acho que o OP esteja procurando por isso.
nyuszika7h
7
Nem --is-inside-work-treenem --is-inside-git-dirvai funcionar quando você está fora de um repositório git. consulte: groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
fisherwebdev
7
Isso falhará se o diretório git for algo diferente de .git. Para maior robustez, omita o [ -d .git ]e apenas use git rev-parse ....
Peter John Acklam
133

Você pode usar:

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

O que imprimirá 'true' se você estiver em uma árvore de trabalho de repositórios git.

Observe que ele ainda retorna a saída para STDERR se você estiver fora de um repositório git (e não imprimir 'false').

Retirado desta resposta: https://stackoverflow.com/a/2044714/12983

TM.
fonte
Esta é a maneira mais simples de verificar isso.
calbertts
3
Esta continua a imprimir false para um repositório nua que não tem nenhuma árvore de trabalho
noggin182
Isso não considera o subdiretório. Preciso verificar se git rev-parse --show-toplevelcorresponde à subpasta que estou verificando
alper 21/03
A resposta escolhida nem imprimiu nada. Este funcionou.
ScottyBlades
47

Use git rev-parse --git-dir

se git rev-parse --git-dir> / dev / null 2> & 1; então
  : # Este é um repositório git válido (mas o trabalho atual
    O diretório # pode não ser o nível superior.
    # Verifique a saída do comando git rev-parse se você se importa)
outro
  : # este não é um repositório git
fi
William Pursell
fonte
7

Não tenho certeza se existe uma maneira publicamente acessível / documentada de fazer isso (existem algumas funções internas do git que você pode usar / abusar na própria fonte git)

Você poderia fazer algo como;

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

Com base na resposta de @Alex Cory :

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

não contém nenhuma operação redundante e funciona no -emodo

  • Como o @ go2null observou , isso não funcionará em um repositório simples. Se você deseja trabalhar com um repositório simples por qualquer motivo, basta verificar se há git rev-parseêxito, ignorando sua saída.
    • Eu não considero isso uma desvantagem, porque a linha acima é indicada para scripts e praticamente todos os gitcomandos são válidos apenas dentro de uma árvore de trabalho. Portanto, para fins de script, você provavelmente está interessado em estar não apenas dentro de um "repositório git", mas dentro de uma árvore de trabalho.
ivan_pozdeev
fonte
isto falhar dentro de um git repo nua
go2null
Em vez de verificar a saída, é uma prática recomendada verificar o valor de retorno. Não invoque [nada. Basta fazer if git rev-parse --is-inside-work-tree; then ...(com redirecionamentos como desejado.)
William Pursell
1
@WilliamPursell verificar o valor de saída não funciona aqui: stackoverflow.com/questions/2180270/…
ivan_pozdeev
@Ivan_pozdeev Depende da sua definição de "trabalho". Nesse caso, eu diria que verificar o valor de retorno funciona, enquanto verificar a saída não. Em qualquer um dos casos, da perspectiva das melhores práticas para escrever código no shell, é mais apropriado verificar o valor de retorno.
William Pursell
@WilliamPursell, se você ler o comentário vinculado, saberá o que quero dizer com "não funciona" aqui.
ivan_pozdeev 7/02/19
6

Outra solução é verificar o código de saída do comando.

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

Isso imprimirá 1 se você estiver em uma pasta de repositório git.


fonte
Observe que isso terá rc 0 mesmo se você estiver dentro do .gitdiretório - o que você pode ou não querer.
ivan_pozdeev
O Git foi escrito de maneira sadia, para que você possa fechar os arquivos que não deseja git rev-parse 2>&-.
jthill
3

Esta resposta fornece uma função shell POSIX de exemplo e um exemplo de uso para complementar a resposta do @ jabbie .

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

gitretorna nível de erro 0se estiver dentro de um repositório git; caso contrário, retorna nível de erro 128. (Também retorna trueoufalse se estiver dentro de um repositório git.)

Exemplo 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
fonte
Não suficiente. No interior .git, terá sucesso, mas será impresso false.
ivan_pozdeev
@ivan_pozdeev: Se git rev-parse --is-inside-work-treeretornos trueou falseentão ele é dentro de um repositório git, e é isso que a função retorna. isto é, a função está correta #
go2null go 29/11
Para expandir, veja a descrição na resposta, o valor retornado do git é ignorado, o nível de erro é o que é usado.
Go2null 29/11/18
2

isso funciona para mim. Você ainda recebe os erros, mas eles são fáceis de suprimir. também funciona de dentro de subpastas!

status do git> / dev / null 2> & 1 && echo Olá, mundo!

Você pode colocar isso em uma instrução if then se precisar fazer mais condicionalmente.

CharlesTWall3
fonte
2
Bom o suficiente para muitos casos, talvez, mas falha em um repositório simples do Git.
Curinga
3
git statuspode ser muito lento em um repo grande / antigo. Eu não o usaria para esse fim.
henrebotha 21/01
1

Por que não usar códigos de saída? Se um repositório git existir no diretório atual, os comandos git branche git tagretornarão o código de saída 0; caso contrário, um código de saída diferente de zero será retornado. Dessa forma, você pode determinar se um repositório git existe ou não. Simplesmente, você pode executar:

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

Vantagem : Flexibe. Ele funciona para repositórios vazios e não vazios e em sh, zsh e bash.

Explicação

  1. git tag: Obtendo tags do repositório para determinar se existe ou não.
  2. > /dev/null 2>&1: Impedindo a impressão de qualquer coisa, incluindo saídas normais e de erro.
  3. [ $? -eq 0 ]: Verifique se o comando anterior retornou com o código de saída 0 ou não. Como você deve saber, toda saída diferente de zero significa que algo de ruim aconteceu. $?recebe o código de saída do comando anterior, e [, -eqe ]realizar a comparação.

Como exemplo, você pode criar um arquivo nomeado check-git-repocom o seguinte conteúdo, torná-lo executável e executá-lo:

#!/bin/sh

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

# verifique se o 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
fonte
Esta não é uma prática recomendada. Se executado fora de um diretório ativo, você receberá "fatal: não um repositório git (ou qualquer um dos diretórios pai): .git" escrito no stderr e "não, não é um repositório git" no stdout. Não há necessidade de invocar [aqui. Apenas faça:if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
William Pursell
No meu caso, estou confortável com isso e quero acompanhar essa falha nos meus logs. Felicidades!
21419 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

Obrigado ivan_pozdeev , Agora eu tenho um teste se dentro do diretório .git o código não será executado, para que não haja erros impressos ou status de saída falso.

O " ! [[$ (Pwd) = .git / || $ (pwd) = * .git]] " testa se você não está dentro de um repositório .git, então ele executa o comando git. O comando do tipo embutido é usado para verificar se você tem o git instalado ou se está dentro do seu PATH. ver tipo de ajuda

Jetchisel
fonte
0

Que tal isso:

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

Você pode adicionar ou substituir seu $ PS1 no zshrc por uma ou outra ferramenta de prompt do git. Dessa forma, você pode ser convenientemente informado se está em um repositório git e se o estado do repositório está.

jxqz
fonte
3
A pergunta inteira do OP era como fazê-lo de dentro de um script
Andrew C
e como __git_ps1 não pode ser usado em um script? O objetivo principal do git-prompt é verificar o status do git do diretório atual, o que foi solicitado.
Jxqz # 25/14
-1
! git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { 
  printf '%s\n\n' "GIT repository detected." && git status
}

O ! nega, mesmo que você execute isso em um diretório que não seja um repositório git, ele não fornecerá alguns erros fatais

O > / dev / null 2> & 1 envia as mensagens para / dev / null, pois você está logo após o status de saída. O {} é para agrupamentos de comandos, portanto, todos os comandos após o || será executado se o git rev-parse for bem-sucedido, pois usamos a! que negou o status de saída do git rev-parse. O printf serve apenas para imprimir algumas mensagens e status git para imprimir o status do repositório.

Envolva-o em uma função ou coloque-o em um script. Espero que isto ajude

Jetchisel
fonte
1
Não suficiente. No interior .git, terá sucesso, mas será impresso false.
ivan_pozdeev