Explique qual regra gitignore está ignorando meu arquivo

Existe alguma maneira de ver porque algum arquivo está sendo ignorado pelo git (ou seja, qual regra em um arquivo .gitignore está causando o arquivo a ser ignorado)?

Imagine que eu tenho isso (ou um cenário muito mais complexo, com centenas de pastas e dezenas de arquivos .gitignore :

 / -.gitignore -folder/ -.gitignore -subfolder/ -.gitignore -file.txt 

Se eu rodar git add folder/subfolder/file.txt git pode reclamar de ser ignorado:

 The following paths are ignored by one of your .gitignore files: folder/subfolder/file.txt Use -f if you really want to add them. 

Existe alguma maneira de saber qual de todos os possíveis .gitignore tem uma regra para ignorar esse arquivo, e também mostrar a regra? Gostar:

 The following paths are ignored by your folder/.gitignore file (line 12: *.txt) folder/subfolder/file.txt Use -f if you really want to add them. 

Ou apenas:

 $ git why-is-ignored folder/subfolder/file.txt folder/.gitignore:12:*.txt 

 git check-ignore -v filename 

Veja a man page para mais detalhes.

A resposta original segue:

O git atualmente não fornece nada como isto. Mas depois de ver a sua pergunta, fiz algumas pesquisas e descobri que em 2009 esse recurso foi solicitado e parcialmente implementado . Depois de ler o tópico, percebi que não seria muito trabalhoso fazer isso corretamente, então comecei a trabalhar em um patch e espero tê-lo terminado no próximo dia ou dois. Eu atualizarei esta resposta quando estiver pronta.

ATUALIZAÇÃO: Uau, isso foi muito mais difícil do que eu esperava. As entranhas do tratamento de exclusão do git são bastante enigmáticas. Enfim, aqui está uma série quase concluída de commits que se aplicam ao branch master upstream de hoje. O conjunto de testes está 99% completo, mas ainda não concluí o manuseio da opção --stdin . Espero que eu administre isso neste fim de semana, e então envie meus patches para a lista de discussão do git.

Enquanto isso, eu definitivamente gostaria de testar de qualquer um que seja capaz de fazê-lo – basta clonar o meu git fork , verificar o branch check-ignore e compilá-lo normalmente.

ATUALIZAÇÃO 2: Está feito! A versão mais recente está no github como acima, e enviei a série de correções para a lista de discussão do git para revisão por pares. Vamos ver o que eles pensam …

ATUALIZAÇÃO 3: Depois de vários meses de revisões de hacking / patch / discussões / espera, estou satisfeito em poder dizer que este recurso agora atingiu a ramificação master do git , e estará disponível no próximo lançamento (1.8.2, esperado 8 de março de 2013). Aqui está a página de check-ignore manual . Ufa, isso foi muito mais trabalho do que eu esperava!

ATUALIZAÇÃO 4: Se você está interessado na história completa sobre como esta resposta evoluiu e o recurso foi implementado, confira o episódio # 32 do podcast GitMinutes .

Atualização do git 2.8 (março de 2016):

 GIT_TRACE_EXCLUDE=1 git status 

Veja ” Uma maneira de validar o arquivo .gitignore

Isso é complementar ao git check-ignore -v descrito abaixo.


Resposta original: setembro de 2013 (git 1.8.2, depois 1.8.5+):

git check-ignore melhora novamente no git 1.8.5 / 1.9 (Q4 2013) :

git check-ignore ” segue a mesma regra que ” git add ” e ” git status “, pois o mecanismo de ignorar / excluir não entra em vigor nos caminhos que já foram rastreados.
Com a opção ” --no-index “, ele pode ser usado para diagnosticar quais caminhos que deveriam ter sido ignorados foram adicionados por engano ao índice .

Veja commit 8231fa6 em https://github.com/flashydave :

check-ignore atualmente mostra como .gitignore regras do .gitignore tratariam os caminhos não .gitignore . Caminhos rastreados não geram saída útil.
Isso impede a debugging de porque um caminho foi rastreado inesperadamente, a menos que esse caminho seja removido do índice com git rm --cached .

A opção --no-index diz ao comando para ignorar a verificação do caminho que está no índice e, portanto, permite que os caminhos rastreados sejam verificados também.

Embora este comportamento se desvie das características do git status git add e git status é improvável que seu caso de uso cause qualquer confusão ao usuário.

Os scripts de teste são aumentados para verificar essa opção em relação aos padrões ignorados para garantir o comportamento correto.


 --no-index:: 

Não procure no índice ao realizar as verificações.
Isso pode ser usado:

  • para depurar porque um caminho foi rastreado por exemplo, git add . e não foi ignorado pelas regras como esperado pelo usuário ou
  • ao desenvolver padrões incluindo negação para corresponder a um caminho adicionado anteriormente com git add -f .

Não consigo encontrar nada na página man, mas aqui está um script rápido e sujo que irá verificar o seu arquivo em cada diretório pai para ver se ele pode ser adicionado ao git-add. Execute-o no diretório que contém o arquivo do problema como:

 test-add.sh STOP_DIR FILENAME 

onde STOP_DIR é o diretório de nível superior do projeto Git e FILENAME é o nome do arquivo com problema (sem um caminho). Ele cria um arquivo vazio com o mesmo nome em cada nível da hierarquia (se não existir) e tenta um git add -n para ver se ele pode ser adicionado (ele é limpo depois de si mesmo). Produz algo como:

 FAILED: /dir/1/2/3 SUCCEEDED: /dir/1/2 

O roteiro:

 #!/usr/bin/env bash TOP=$1 FILE=$2 DIR=`pwd` while : ; do TMPFILE=1 F=$DIR/$FILE if [ ! -f $F ]; then touch $F TMPFILE=0 fi git add -n $F >/dev/null 2>&1 if [ $? = 0 ]; then echo "SUCCEEDED: $DIR" else echo "FAILED: $DIR" fi if [ $TMPFILE = 0 ]; then rm $F fi DIR=${DIR%/*} if [ "$DIR" \< "$TOP" ]; then break fi done 

Para adicionar à resposta principal do uso do git check-ignore -v filename (obrigado BTW) eu descobri que meu arquivo .gitignore estava bloqueando tudo porque havia uma nova linha após um caractere curinga, então eu tive:

* .sublime-project

como um exemplo. Acabei de remover a nova linha e voila! Foi consertado.