Comando Git para mostrar quais arquivos específicos são ignorados pelo .gitignore

645

Estou molhando os pés com o Git e tenho o seguinte problema:

Minha árvore de origem do projeto:

/
|
+--src/
+----refs/
+----...
|
+--vendor/
+----...

Eu tenho um código (atualmente MEF) na minha filial de fornecedores que eu compilaremos lá e depois moveremos as referências para /src/refsonde o projeto as seleciona.

Meu problema é que tenho meu .gitignoreconjunto para ignorar *.dlle *.pdb. Eu posso fazer um git add -f bar.dllpara forçar a adição do arquivo ignorado, o que é bom, o problema é que não consigo descobrir a lista de quais arquivos existem que são ignorados.

Quero listar os arquivos ignorados para garantir que não esqueça de adicioná-los.

Eu li a página de manual git ls-filese não consigo fazê-la funcionar. Parece-me que git ls-files --exclude-standard -ideve fazer o que eu quero. o que estou perdendo?

Andrew Burns
fonte
12
Estes dias, você não iria usar git-ls-arquivos, mas sim 'git ls-files'
Wojo
7
Peço a você que verifique a resposta de riyad como correta, já que é a única que admite que não há maneira garantida de fazer isso usando apenas os comandos git (incluindo o git cleantruque), como demonstrado aqui . Além disso, recomendo o exemplo "excluir-de" no seu resumo, pois esse fato não presta atenção a nenhum arquivo .gitignore. Peço isso especialmente porque esta página é a principal resposta do Google.
Alexander Ave
Ponto rápido no "Resumo do que funciona": a página do manual "Git ls-files" explica que o "-i" significa incluir arquivos excluídos para a saída ls. Eu tive o mesmo mal-entendido, até ler 'devagar'. ;-)
será
2
As respostas devem aparecer em uma resposta e não em uma edição da pergunta.
Flimm
Eu tenho git config --global alias.ls ls-files --exclude-standard, e isso faz a resposta a esta pergunta git ls -i.
jthill

Respostas:

662

Notas:


Também interessante (mencionado no qwertymk de resposta ), você também pode usar o git check-ignore -vcomando, pelo menos no Unix ( não funciona em um CMD do Windows sessão)

git check-ignore *
git check-ignore -v *

O segundo exibe a regra real da .gitignorequal faz com que um arquivo seja ignorado no seu repositório git.
No Unix, usando " O que se expande para todos os arquivos no diretório atual recursivamente? " E um bash4 +:

git check-ignore **/*

(ou um find -execcomando)

Nota: https://stackoverflow.com/users/351947/Rafi B. sugere nos comentários para evitar a globstar (arriscada) :

git check-ignore -v $(find . -type f -print)

Certifique-se de excluir os arquivos da .git/subpasta.


Resposta original 42009)

git ls-files -i

deve funcionar, exceto que seu código fonte indica:

if (show_ignored && !exc_given) {
                fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
                        argv[0]);

exc_given ?

Acontece que ele precisa de mais um parâmetro após o -ipara realmente listar qualquer coisa:

Tentar:

git ls-files -i --exclude-from=[Path_To_Your_Global].gitignore

(mas isso listaria apenas o objeto em cache (não ignorado), com um filtro, para que não seja exatamente o que você deseja)


Exemplo:

$ cat .git/ignore
# ignore objects and archives, anywhere in the tree.
*.[oa]
$ cat Documentation/.gitignore
# ignore generated html files,
*.html
# except foo.html which is maintained by hand
!foo.html
$ git ls-files --ignored \
    --exclude='Documentation/*.[0-9]' \
    --exclude-from=.git/ignore \
    --exclude-per-directory=.gitignore

Na verdade, no meu arquivo 'gitignore' (chamado 'excluir'), encontro uma linha de comando que pode ajudá-lo:

F:\prog\git\test\.git\info>type exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

Assim....

git ls-files --others --ignored --exclude-from=.git/info/exclude
git ls-files -o -i --exclude-from=.git/info/exclude

git ls-files --others --ignored --exclude-standard
git ls-files -o -i --exclude-standard

deve fazer o truque.

Conforme mencionado na página do manual ls-files , --othersé a parte importante, para mostrar arquivos não armazenados em cache, não confirmados e normalmente ignorados.

--exclude_standardnão é apenas um atalho, mas uma maneira de incluir todas as configurações padrão de "padrões ignorados".

exclude-standard
Adicione as exclusões git padrão: .git/info/exclude, .gitignoreem cada diretório, e a user's global exclusion file.

VonC
fonte
@VocC, pelo meu entendimento desses testes , a resposta que você recomenda no topo simplesmente pode ter grandes falhas. É por isso que eu normalmente recomendaria a resposta de riyad .
Alexander Ave
2
Desde Git v2.13.2 Lançamento: git status --ignoredparece que também mostram arquivos untracked: github.com/git/git/blob/master/Documentation/RelNotes/...
Pau
1
uau, git check-ignore -v *funciona muito bem, pois mostra onde a configuração foi aplicada. Obrigado.
Hoang Tran
@ MikeD Para fazer o * / funcionar (ou, na verdade, você pode fazer **), você precisa que o globstar seja definido shopt -s globstardepois que ele funcione.
Veda
Sem ativar (arriscado) globstar:git check-ignore -v $(find . -type f -print)
rafi
484

Existe uma maneira muito mais simples de fazer isso (git 1.7.6+):

git status --ignored

Consulte Existe uma maneira de dizer ao git-status para ignorar os efeitos dos arquivos .gitignore?

Penghe Geng
fonte
3
Qual versão do git você está usando? O meu (1.7.0.4) diz error: unknown option 'ignored'. Mesmo adicionar -scomo sugerido na postagem vinculada não funcionou.
Alexander Ave
3
Minha versão é 1.7.6. Outra versão 1.7.5.1 é a que requer -s. Você pode tentar git status -hpara ver se --ignoredé suportado
Penghe Geng
1
Eu acho que simplesmente ainda não é suportado na 1.7.0.4. Meu outro computador tem 1.7.9 ea bandeira --ignored está lá
Alexander Ave
4
Eu tentei todas as soluções nesta página. Este é o melhor. Mostra arquivos e diretórios. Esse recurso provavelmente não estava disponível quando esta pergunta foi feita originalmente. (By the way, todas as soluções não funcionará corretamente com uma nova marca "git init" até que você tenha pelo menos encenado mudanças.)
wisbucky
12
Isso é certamente muito melhor do que a resposta aceita. Também é muito mais seguro que a git clean -ndXsolução, porque a rara situação em que esquecemos erroneamente os sinalizadores terá um efeito irrevogável no repositório, pois os arquivos não rastreados são excluídos. Então é perigoso. Pelo contrário, git status --ignoredé sempre seguro, mesmo quando digitado erroneamente e é natural lembrar.
Ioannis Filippidis
400

Outra opção bastante limpa (sem trocadilhos):

git clean -ndX

Explicação:

$ git help clean

git-clean - Remove untracked files from the working tree
-n, --dry-run - Don't actually remove anything, just show what would be done.
-d - Remove untracked directories in addition to untracked files.
-X - Remove only files ignored by Git.

Nota: Esta solução não mostrará arquivos ignorados que já foram removidos.

ma11hew28
fonte
Astucioso ... no entanto, o motivo pelo qual fiz a pergunta original foi para garantir que os arquivos do fornecedor (* .dll) que deveriam estar lá estavam ... então, excluí-los não seria o resultado desejado. NO ENTANTO: é bom saber que eu mudei minha estratégia de ignorar * .dll para ignorar minha pasta de saída de compilação (mas não minhas pastas de fornecedores). Essa seria uma boa alternativa make cleane muito útil em um servidor de compilação.
Andrew Burns
2
Estou usando o git versão 1.7.0.4, e os dois comandos ('git ls-files -o -i --exclude-standard', 'git clean -dXn') não são equivalentes. O primeiro me mostra 4 arquivos e o segundo apenas dois. (.gitignore ~, index.php ~, sql / create_users.sql ~, www / index.php ~) (removeria .gitignore ~, removeria index.php ~). Estou sentindo falta de algo aqui?
Cesar
@VonC, doce! Obrigado! @ Cesar, não tenho certeza. Eu não estou tão familiarizado com isso git ls-files -o -i --exclude-standard. git clean -dXnsempre foi o que eu queria, mas não mostra arquivos ignorados que já foram removidos. git ls-files -o -i --exclude-standardpode fazer isso. Então, isso pode estar causando a diferença.
ma11hew28
3
Uma coisa minúscula - pode ser uma boa idéia digitar a nprimeira, menos chance de excluir acidentalmente dessa maneira; git clean -ndX
Tobias Cohen
1
@TobiasCohen nice! Eu atualizei a resposta com sua sugestão. É mais seguro. Embora, se você deixar de fora o nGit, o padrão é fatal: clean.requireForce defaults to true and neither -n nor -f given; refusing to clean. Ainda é bastante seguro, mas digitar o nprimeiro é ainda mais seguro! :)
ma11hew28
39

Embora geralmente correta, sua solução não funciona em todas as circunstâncias. Suponha um dir de repo como este:

# ls **/*                                                                                                       
doc/index.html  README.txt  tmp/dir0/file0  tmp/file1  tmp/file2

doc:
index.html

tmp:
dir0  file1  file2

tmp/dir0:
file0

e um .gitignore como este:

# cat .gitignore
doc
tmp/*

Isso ignora o docdiretório e todos os arquivos abaixo tmp. O Git funciona conforme o esperado, mas o comando fornecido para listar os arquivos ignorados não. Vamos dar uma olhada no que o git tem a dizer:

# git ls-files --others --ignored --exclude-standard                                                            
tmp/file1
tmp/file2

Observe que docestá faltando na lista. Você pode obtê-lo com:

# git ls-files --others --ignored --exclude-standard --directory                                                
doc/

Observe a --directoryopção adicional .

Pelo que sei, não existe um comando para listar todos os arquivos ignorados de uma só vez. Mas não sei por tmp/dir0que não aparece.

riyad
fonte
2
Isso me deu o que eu queria, enquanto os outros não (no meu caso particular) ... obrigado! É frustrante ter que executar dois comandos, mas com um diretório ignorado, a opção --directory pelo menos me acha isso, e posso canalizá-lo para um comando find para localizar os arquivos. Obrigado!
Lindes 26/05
Isso faz tudo de uma vez e expande os diretórios:(git ls-files -oi --exclude-standard; git ls-files -oi --exclude-standard --directory) | perl -nle '$seen{$_}++||next;if(-d){system"find",$_,"-type","f"}else{print}'
Dee Newcum 26/06/12
17

Agora o Git tem essa funcionalidade integrada

git check-ignore *

Claro que você pode mudar a glob para algo como **/*.dllno seu caso

Referência Git

qwertymk
fonte
7
git check-ignore **/*para incluir arquivos em subdiretórios
mzimmer
isso lista apenas os diretórios de nível superior.
Radon8472
13

Deve ser suficiente usar

git ls-files --others -i --exclude-standard

como isso cobre tudo coberto por

git ls-files --others -i --exclude-from=.git/info/exclude

portanto, o último é redundante.


Você pode facilitar isso adicionando um alias ao seu ~/.gitconfigarquivo:

git config --global alias.ignored "ls-files --others -i --exclude-standard"

Agora você pode apenas digitar git ignoredpara ver a lista. Muito mais fácil de lembrar e mais rápido de digitar.

Se você preferir uma exibição mais sucinta da solução de Jason Geng, poderá adicionar um alias para isso assim:

git config --global alias.ignored "status --ignored -s"

No entanto, a saída mais detalhada é mais útil para solucionar problemas com os arquivos .gitignore, pois lista todos os arquivos que são ignorados. Você normalmente canaliza os resultados greppara ver se um arquivo que você espera ser ignorado está lá ou se um arquivo que você não deseja ignorar está lá.

git ignored | grep some-file-that-isnt-being-ignored-properly

Então, quando você só quer ver uma exibição curta, é fácil lembrar e digitar

git status --ignored

( -sNormalmente, isso pode ser deixado de lado.)

iconoclasta
fonte
Isso nunca funcionou para mim, porque você precisa listar esses arquivos manualmente. git status --ignoredobras sobre Debian sid mas pode ser muito novo ... mas aparentemente ele foi adicionado devido à demanda popular ;-)
mirabilos
1
Por "trabalha no Debian sid", suponho que você queira dizer "trabalha com a versão do Git instalada por padrão no Debian sid"? Você deve realmente evitar se deixar refém pelas versões dos utilitários incluídos em sua distribuição. Você pode atualizá-los independentemente da própria distribuição.
Iconoclast
12

Veja como imprimir a lista completa de arquivos na árvore de trabalho que correspondem aos padrões localizados em qualquer lugar nas várias fontes de gitignore do Git (se você estiver usando o GNU find):

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose

Ele verificará todos os arquivos na ramificação atual do repositório (a menos que você os tenha excluído localmente).

E também identifica as linhas de origem específicas do gitignore.

O Git continua a rastrear alterações em alguns arquivos que correspondem aos padrões do gitignore, simplesmente porque esses arquivos já foram adicionados. Útil, o comando acima exibe esses arquivos também.

Padrões de gitignore negativos também são correspondidos. No entanto, eles são facilmente distinguíveis na lista, porque começam com !.

Se você estiver usando o Windows, o Git Bash inclui o GNU find(conforme revelado por find --version).

Se a lista for longa (e você tiver rev), você poderá exibi-las por extensão (um pouco) também:

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose \
| rev | sort | rev

Para mais detalhes, veja man find, man git-check-ignore, man rev, e man sort.

O objetivo de toda essa abordagem é que o Git (o software) está mudando rapidamente e é altamente complexo. Por outro lado, os GNU's findsão extremamente estáveis ​​(pelo menos, em seus recursos usados ​​aqui). Portanto, qualquer pessoa que deseje ser competitivo, demonstrando seu profundo conhecimento do Git, responderá à pergunta de uma maneira diferente.

Qual a melhor resposta? Essa resposta minimiza deliberadamente sua dependência do conhecimento do Git, visando atingir a meta de estabilidade e simplicidade por meio da modularidade (isolamento de informações) e foi projetada para durar muito tempo.

MarkDBlackwell
fonte
Muito obrigado! Eu estava lutando para descobrir por que alguns dos meus novos arquivos de origem ocasionalmente estavam ausentes dos meus commits. Acontece que eu tinha um padrão: bin *, que pensei que corresponderia apenas a nomes de arquivos / diretórios começando com bin, mas, em vez disso, corresponde a qualquer coisa que inclua bin no caminho completo de um arquivo / diretório! Acho que meu problema vem de um mal-entendido da semântica precisa da correspondência de padrões no .gitignore. Seu script de duas linhas me ajudou a encontrar esse erro!
Nicolas Rouquette
1

(estendendo as outras respostas)

Observe que git check-ignoreusa o comprometido .gitignoree não o da sua árvore de trabalho! Para jogar sem poluir seu histórico do git, você pode livremente tentar editá-lo e depois confirmar com um git commit --amend.

Esse problema ocorre principalmente se você precisar de uma solução alternativa para o problema, pois o git não segue os diretórios. Entre no .gitignore:

dirtokeep/**
!dirtokeep/.keep

.keepdeve ser um arquivo de tamanho zero em dirtokeep.

O resultado será que tudo nos dirtokeepserá ignorado, exceto dirtokeep/.keep , o que resultará também que o dirtokeepdiretório será construído na clone / checkout.

peterh - Restabelecer Monica
fonte
0

Supondo que existam alguns diretórios ignorados, por que não usar "git status node / logs /", que informará quais arquivos devem ser adicionados? No diretório, tenho um arquivo de texto que não faz parte da saída de status, por exemplo:

No mestre da filial
Sua filial está atualizada com 'origem / mestre'.
Arquivos não rastreados:
(use "git add ..." para incluir no que será confirmado)

    node/logs/.gitignore 

.gitignore é:

*

! .gitignore

pikknz
fonte