Determina se o diretório de trabalho do Git está limpo de um script

51

Eu tenho um script que executa rsync com um diretório de trabalho do Git como destino. Eu quero que o script tenha um comportamento diferente dependendo se o diretório de trabalho está limpo (sem alterações para confirmar) ou não. Por exemplo, se a saída de git status for a seguinte, quero que o script saia:

git status
Already up-to-date.
# On branch master
nothing to commit (working directory clean)
Everything up-to-date

Se o diretório não estiver limpo, eu gostaria que ele executasse mais alguns comandos.

Como posso verificar a saída como acima em um script de shell?

    
por brentwpeterson 11.09.2014 / 15:24

2 respostas

97

Analisar a saída de git status é uma má ideia porque a saída é destinada a ser legível por humanos, não legível por máquina. Não há garantia de que a saída permanecerá a mesma em versões futuras do Git ou em ambientes configurados de forma diferente.

UVVs comment está no caminho certo, mas infelizmente o código de retorno de git status não muda quando há alterações não confirmadas. No entanto, ele fornece a opção --porcelain , que causa a saída de git status --porcelain a ser formatada em um formato fácil de analisar para scripts, e permanecerão estáveis nas versões do Git e independentemente da configuração do usuário.

Podemos usar a saída vazia de git status --porcelain como um indicador de que não há alterações a serem confirmadas:

if [ -z "$(git status --porcelain)" ]; then 
  # Working directory clean
else 
  # Uncommitted changes
fi

Se não nos preocupamos com arquivos não rastreados no diretório de trabalho, podemos usar o --untracked-files=no para ignorar essas:

if [ -z "$(git status --untracked-files=no --porcelain)" ]; then 
  # Working directory clean excluding untracked files
else 
  # Uncommitted changes in tracked files
fi

Para tornar isso mais robusto contra condições que realmente fazem com que git status falhe sem saída para stdout , podemos refinar a verificação para:

if output=$(git status --porcelain) && [ -z "$output" ]; then
  # Working directory clean
else 
  # Uncommitted changes
fi

Também vale a pena notar que, embora git status não forneça um código de saída significativo quando o diretório de trabalho está sujo, git diff fornece o --exit-code opção, o que faz com que se comporte de forma semelhante ao diff utilitário, ou seja, saindo com status 1 quando houve diferenças e 0 quando nenhum foi encontrado.

Usando isso, podemos verificar alterações não sincronizadas com:

git diff --exit-code

e encenado, mas não confirmado, alterações com:

git diff --cached --exit-code

Embora git diff possa relatar arquivos não acompanhados em submódulos por meio de argumentos apropriados para --ignore-submodules , infelizmente parece que não há maneira de fazer com que seja reportado em arquivos não rastreados no diretório de trabalho atual. Se arquivos não rastreados no diretório de trabalho forem relevantes, git status --porcelain é provavelmente a melhor aposta.

    
por 11.09.2014 / 17:48
9

Uso:

git diff-index --quiet HEAD

O código de retorno reflete o estado do diretório de trabalho (0 = limpo, 1 = sujo). Arquivos não rastreados são ignorados.

    
por 27.09.2017 / 07:41