Explicar qual regra do gitignore está ignorando meu arquivo

310

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

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

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

Se eu rodar, o git add folder/subfolder/file.txtgit pode reclamar por ter sido 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 quais de todos os possíveis .gitignoretêm 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
Carlos Campderrós
fonte
4
Nota: git check-ignoreem breve (git1.8.5 / 1.9) terá uma --no-indexopção. Veja minha resposta abaixo
VonC
Nota: GIT_TRACE_EXCLUDE=1 git statusem breve será uma maneira adicional de depurar .gitignoreregras. Veja minha resposta editada abaixo
VonC 1/16/16
Postagem relevante no blog: danielcompton.net/2016/04/21/… .
krlmlr

Respostas:

643
git check-ignore -v filename

Veja a página de manual para mais detalhes.

A resposta original segue:

Atualmente, o git não fornece nada parecido com isso. Mas, depois de ver sua pergunta, pesquisei no Google 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 fazê-lo corretamente, então comecei o trabalho em um patch e espero que ele termine nos próximos dois dias. Vou atualizar esta resposta quando estiver pronta.

UPDATE: Uau, isso foi muito mais difícil do que eu esperava. As entranhas do gittratamento de exclusão são bastante enigmáticas. De qualquer forma, aqui está uma série quase finalizada de confirmações que se aplicam ao masterramo upstream de hoje . O conjunto de testes está 99% completo, mas ainda não terminei o manuseio da --stdinopção. Espero que eu consiga gerenciar esse final de semana e depois envie meus patches para a lista de discussão git.

Enquanto isso, eu definitivamente aceitaria os testes de qualquer pessoa capaz de fazê-lo - basta clonar no meu gitgarfo , verificar o check-ignoreramo e compilá-lo normalmente.

ATUALIZAÇÃO 2: Está feito! A versão mais recente está no github, conforme descrito acima, e enviei a série de patches 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 hackers / revisões de patches / discussões / espera, estou muito satisfeito em poder dizer que esse recurso chegou ao masterramo do git e estará disponível no próximo lançamento (1.8.2, esperado 8 Março de 2013). Aqui está a check-ignorepágina do manual . Ufa, isso foi muito mais trabalho do que eu esperava!

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

Adam Spires
fonte
2
Estou usando o 1.8.2 e git check-ignorenão faz nada.
perfil completo de zakdances
3
@yourfriendzak Sem sombra de dúvida, git check-ignoreestá presente e funcionando na 1.8.2. Se o comportamento não for o que você espera, sugiro que você (re) leia a página de manual e, se ainda não for, envie um relatório de erro adequado na lista de discussão do git. Apenas dizer que não faz nada não ajuda muito. Espero que você provavelmente o tenha executado em um arquivo não ignorado e esteja esperando alguma saída incorretamente (embora provavelmente adicionarei suporte --show-unmatchedao --verbosemodo de saída no futuro).
Adam Spires
1
@AdamSpiers você está certo. Eu deveria ter especificado que, quando executo o comando, nada é impresso. Nenhuma mensagem de erro, nenhuma mensagem de sucesso, nenhuma informação. Apenas o próximo prompt em branco aparecendo. Então, estou correto ao supor que "nenhuma saída" é o comportamento esperado em determinadas circunstâncias?
Zakdances 03/04
1
@AdamSpiers muito obrigado por isso! Após três dias de investigação, você acabou de me ajudar a rastrear a causa de uma compilação interrompida devido a um arquivo globalmente ignorado em .gitignore_global! Eu nem sabia que isso era uma coisa!
BenBtg
3
Não é todo dia que se vê um desenvolvedor do Stack Overflow fazer tantas alterações para implementar um recurso de desenvolvedor. Uau e respeito.
user3613932
18

Atualize o git 2.8 (março de 2016):

GIT_TRACE_EXCLUDE=1 git status

Vejo " Uma maneira de validar o .gitignorearquivo "

Isso é complementar ao git check-ignore -vdescrito abaixo.


Resposta original: setembro de 2013 (git 1.8.2 e 1.8.5 ou posterior):

git check-ignore melhora novamente em git 1.8.5 / 1.9 (quarto trimestre de 2013) :

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

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

check-ignoreatualmente mostra como as .gitignoreregras tratariam caminhos não rastreados. Caminhos rastreados não geram resultados úteis.
Isso evita a depuração do motivo pelo qual um caminho foi rastreado inesperadamente, a menos que esse caminho seja removido primeiro do índice com git rm --cached <path>.

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

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

Os scripts de teste são aumentados para verificar esta opção contra os 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 por que um caminho foi rastreado por git add . e não foi ignorado pelas regras conforme o esperado pelo usuário ou
  • ao desenvolver padrões, incluindo negação, para corresponder a um caminho adicionado anteriormente git add -f.
VonC
fonte
4

Não consigo encontrar nada na página do manual, mas aqui está um script rápido e sujo que verificará seu arquivo em cada diretório pai para ver se ele pode ser adicionado ao git. 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 a git add -npara ver se pode ser adicionado (ele limpa depois de si mesmo). Ele gera algo como:

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

O script:

#!/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 
edoloughlin
fonte
1

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

* .sublime-project

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

rekordboy
fonte