A chave para criar scripts com segurança no Git é usar os comandos 'encanamento'.
Os desenvolvedores tomam cuidado ao alterar os comandos de encanamento para garantir que eles forneçam interfaces muito estáveis (ou seja, uma determinada combinação de estado do repositório, stdin, opções de linha de comando, argumentos etc.) produzirá a mesma saída em todas as versões do Git em que o comando / opção existe). Novas variações de saída nos comandos de encanamento podem ser introduzidas por meio de novas opções, mas isso não pode causar problemas para programas que já foram gravados em versões mais antigas (eles não usariam as novas opções, pois não existiam (ou pelo menos eram não utilizado) no momento em que o script foi escrito).
Infelizmente, os comandos Git 'cotidianos' são os comandos 'porcelana'; portanto, a maioria dos usuários do Git pode não estar familiarizada com os comandos de encanamento. A distinção entre porcelana e comando de encanamento é feita na página principal do git (consulte as subseções intituladas Comandos de alto nível (porcelana) e comandos de baixo nível (encanamento) .
Para descobrir mudanças não confirmadas, você provavelmente precisará git diff-index
(comparar o índice (e talvez rastrear bits da árvore de trabalho) com outras árvores (por exemplo HEAD
)), talvez git diff-files
(comparar a árvore de trabalho com o índice) e possivelmente git ls-files
(listar arquivos; por exemplo, lista não rastreada) , arquivos não ignorados).
(Observe que nos comandos abaixo, HEAD --
é usado em vez de HEAD
porque, caso contrário, o comando falhará se houver um arquivo nomeado HEAD
.)
Para verificar se um repositório organizou alterações (ainda não confirmadas), use isto:
git diff-index --quiet --cached HEAD --
- Se sair com
0
, não houve diferenças ( 1
significa que houve diferenças).
Para verificar se uma árvore de trabalho possui alterações que podem ser testadas:
git diff-files --quiet
- O código de saída é o mesmo que para
git diff-index
( 0
== sem diferenças; 1
== diferenças).
Para verificar se a combinação do índice e dos arquivos rastreados na árvore de trabalho tem alterações em relação a HEAD
:
git diff-index --quiet HEAD --
- É como uma combinação dos dois anteriores. Uma diferença principal é que ele ainda relatará "sem diferenças" se você tiver uma mudança faseada que "desfeita" na árvore de trabalho (voltada para o conteúdo que está dentro
HEAD
). Nessa mesma situação, os dois comandos separados retornariam relatórios de "diferenças presentes".
Você também mencionou arquivos não rastreados. Você pode significar “não rastreado e não registrado” ou apenas “não rastreado” (incluindo arquivos ignorados). De qualquer jeito,git ls-files
é a ferramenta para o trabalho:
Para "não rastreado" (incluirá arquivos ignorados, se houver):
git ls-files --others
Para "não rastreado e não registrado":
git ls-files --exclude-standard --others
Meu primeiro pensamento é apenas verificar se esses comandos têm saída:
test -z "$(git ls-files --others)"
- Se sair com
0
, não haverá arquivos não rastreados. Se sair com 1
, haverá arquivos não rastreados.
Há uma pequena chance de que isso traduza saídas anormais de git ls-files
relatórios "sem arquivos não rastreados" (ambos resultam em saídas diferentes de zero do comando acima). Uma versão um pouco mais robusta pode ser assim:
u="$(git ls-files --others)" && test -z "$u"
- A ideia é a mesma do comando anterior, mas permite que erros inesperados
git ls-files
sejam propagados. Nesse caso, uma saída diferente de zero pode significar "existem arquivos não rastreados" ou um erro. Se você deseja que os resultados de "erro" combinem com o resultado "sem arquivos não rastreados", use test -n "$u"
(onde sair de0
significa "alguns arquivos não rastreados" e diferente de zero significa erro ou "nenhum arquivo não rastreado").
Outra idéia é usar --error-unmatch
para causar uma saída diferente de zero quando não houver arquivos não rastreados. Isso também corre o risco de confundir “nenhum arquivo não rastreado” (saída 1
) com “ocorreu um erro” (saída diferente de zero, mas provavelmente 128
). Mas a verificação de códigos de saída 0
vs. 1
vs. diferentes de zero é provavelmente bastante robusta:
git ls-files --others --error-unmatch . >/dev/null 2>&1; ec=$?
if test "$ec" = 0; then
echo some untracked files
elif test "$ec" = 1; then
echo no untracked files
else
echo error from ls-files
fi
Qualquer um dos git ls-files
exemplos acima pode ser --exclude-standard
usado se você quiser considerar apenas arquivos não acompanhados e não rastreados.