TL;DR: se o .gitignore não funciona, o arquivo quase sempre já está rastreado. O git ignora arquivos que ele nunca viu — um arquivo no índice é imune a qualquer regra que você escrever. Descubra a verdade com git check-ignore -v <path>: saída em silêncio significa que o caminho está rastreado e nenhuma regra se aplica. Conserte com git rm --cached <path>, commite, e a regra de ignore passa a valer a partir desse commit. Ordem das regras, armadilhas de negação e pistas falsas do VS Code explicam os casos restantes.
Por que o .gitignore não funciona?
Um mecanismo cobre a maioria dos casos: o arquivo foi commitado antes de a regra existir. O .gitignore não é um filtro que esconde arquivos do git — é uma regra sobre o que o git add deve pegar de um estado não rastreado. Uma vez no índice, o git acompanha as mudanças de conteúdo do arquivo para sempre até você tirá-lo explicitamente do rastreamento. Editar o .gitignore depois do estrago não muda nada para arquivos rastreados — por isso a sequência clássica “commita o .env, entra em pânico, adiciona .env ao .gitignore, commita de novo” continua enviando o segredo a cada push.
Isso morde todo mundo porque o git é quase universal — a pesquisa Stack Overflow de 2022 apontou uso de Git por mais de 93% dos desenvolvedores profissionais (survey.stackoverflow.co) — e cada um desses desenvolvedores um dia escreve uma regra para um arquivo que commitou na semana passada.
O resto do post cobre os casos minoritários: erros de ordem de regras, armadilhas de negação, casos de borda com pastas e a questão do IDE. Mas rode o check-up da próxima seção primeiro — mais de nove vezes em dez ele encerra a investigação.
Como ver qual regra do gitignore está valendo para um arquivo?
O git check-ignore é a ferramenta de diagnóstico, e o silêncio dele é o diagnóstico:
# Imprime a regra correspondente + arquivo + número da linha quando uma regra se aplica
git check-ignore -v debug.log
# .gitignore:3:*.log debug.log
# Não imprime NADA quando nenhuma regra se aplica — o arquivo está rastreado (ou não há regra)
git check-ignore -v src/.env
# (silêncio = o .gitignore não está ignorando este caminho, escreva o que escrever)
# Códigos de saída: 0 = ignorado, 1 = não ignorado — dá para scriptar
git check-ignore -q debug.log && echo "ignored" || echo "tracked or unruly" Lendo a saída do -v: a fonte do ignore (.gitignore, .git/info/exclude ou seu arquivo global de ignore), depois número-da-linha:padrão, depois o caminho. Se uma regra posterior te surpreender, lembre da precedência: a última regra que casa vence, então !important.log depois de *.log re-inclui aquele arquivo.
Por que o gitignore não funciona para arquivos já commitados?
Tire o arquivo do rastreamento, mantenha em disco, commite a remoção:
# Tira um arquivo do rastreamento (a cópia local sobrevive — o --cached mexe só no índice)
git rm --cached .env
git commit -m "stop tracking .env"
# Confirma que a regra de ignore agora vale
git check-ignore -v .env A partir desse commit, o .gitignore manda no caminho: edições nele não aparecem mais no git status, e o git add . não o pega de volta. O arquivo continua no histórico, porém — se era um segredo, tirá-lo do último commit não basta. Rotacionar a credencial é o único conserto real; reescrever histórico é o cosmético (e desfazer o último commit só ajuda enquanto o commit ruim ainda é a ponta).
Para um repositório cheio de lixo commitado antes — saída de build, detritos de editor, node_modules que entrou cedo demais — o desrastreamento em massa é de duas linhas:
git rm -r --cached .
git add .
git commit -m "apply .gitignore to tracked files" Isso reconstrói o índice contra as regras atuais: caminhos ignorados saem, todo o resto é re-adicionado sem mudanças. O diff parece dramático (milhares de deleções) mas não apaga nada do disco. Se o objetivo é apagar esses arquivos, e não só tirá-los do rastreamento, esse é o território do git clean -fdx — veja git remove untracked files, com segurança.
O git ignora arquivos que ele nunca viu. Um arquivo já no índice é imune ao
.gitignore— nenhuma regra que você escrever faz o git esquecê-lo.
Por que o gitignore não funciona para uma pasta?
Três armadilhas específicas de pasta:
1. Barras finais marcam intenção, não mudam o casamento. build e build/ casam com um diretório dos dois jeitos, mas o build/ documenta que você quer só um diretório — um arquivo chamado build sobreviveria. A simetria, porém, falha na re-inclusão (próxima armadilha).
2. Negação não resgata arquivos dentro de um diretório excluído. A documentação do git é inequívoca: “Não é possível re-incluir um arquivo se um diretório pai desse arquivo estiver excluído” (git-scm.com/docs/gitignore). É uma decisão de desempenho — o git pula diretórios excluídos por inteiro em vez de caminhar por eles. Então isto não funciona:
build/
!build/keep.me # regra morta — o git nunca olha dentro de build/ O conserto é excluir o conteúdo, não o diretório:
build/*
!build/keep.me # funciona — o build/ em si continua aberto para inspeção 3. Arquivos .gitignore aninhados vencem no escopo deles. Regras em subdir/.gitignore sobrepõem o arquivo da raiz para caminhos dentro de subdir. Quando o git check-ignore -v cita uma fonte de ignore que você não esperava, normalmente é isso.
Por que o gitignore não funciona no VS Code?
Quase nunca por motivos do VS Code. A visão de Source Control lê o mesmo índice que o git lê, então o sintoma é idêntico: o arquivo já foi commitado, e nenhum restart de IDE muda o índice. Duas realidades vizinhas do VS Code valem saber:
- Cinza no Explorer = ignorado; laranja/amarelo = rastreado com mudanças. Um arquivo aparecendo como modificado depois de você ignorá-lo é a confirmação de que está rastreado — rode o conserto com
git rm --cachedacima. - Um
.gitignoreausente na lista de changes do Explorer significa que a regra funciona — ele nunca aparece como arquivo não rastreado, em primeiro lugar. As pessoas costumam reportar “o VS Code ignora meu gitignore” quando ogit statusdo CLI diverge de uma visão SCM velha; recarregue a janela (Cmd/Ctrl+Shift+P→ “Reload Window”) antes de culpar o git.
.gitignore vs .git/info/exclude vs global: quando usar cada um?
| Arquivo | Escopo | Commitado? | Usar para |
|---|---|---|---|
.gitignore (repo) | Todos que clonarem | Sim | Saída de build, dependências, .env — regras compartilhadas |
.git/info/exclude | Só o seu clone | Não | Bagunça pessoal: .scratch/, detritos de editor |
core.excludesFile (global) | Todos os seus repositórios | Não | Lixo de SO: .DS_Store, Thumbs.db, *.swp |
.gitignore + negação | Repositório | Sim | Re-incluir exceções de config rastreada |
O arquivo global é o que mais desenvolvedor não configura e deveria:
git config --global core.excludesFile ~/.gitignore_global
printf '.DS_Store\nThumbs.db\n*.swp\n' >> ~/.gitignore_global Regra de casa que vale copiar: se a regra beneficia o time inteiro, ela pertence ao repositório; se só beneficia você, pertence ao exclude ou ao arquivo global. Commitar regras pessoais de ignore é como arquivos .gitignore terminam com 300 linhas e ninguém sabe qual metade ainda importa.
Como ignorar mudanças em um arquivo rastreado?
Às vezes você quer o arquivo rastreado (um template de config, um arquivo de settings do IDE) mas quer que edições locais parem de aparecer no git status. Dois flags no git update-index, nenhum dos quais pertence a um workflow de time:
git update-index --skip-worktree config/local.dev # edições locais ficam em silêncio
git update-index --no-skip-worktree config/local.dev # ...e de volta O --skip-worktree é o defensável — ele diz “minha versão local diverge de propósito”. O primo --assume-unchanged é uma promessa de desempenho (“esse arquivo não vai mudar”), não um mecanismo de ignore, e o git pode quebrá-lo em silêncio. Os dois flags falham alto no pull quando o upstream também mudou o arquivo — as respostas duráveis são um config só local via exclude desde a criação, ou um arquivo template (config.example) que o git rastreia e você copia.
O check-up do gitignore em 30 segundos
git check-ignore -v <path> # qual regra? (silêncio = rastreado, sem regra)
git ls-files --error-unmatch <path> # está rastreado, afinal?
git rm --cached <path> # tira do rastreamento, mantém em disco
git commit -m "stop tracking <path>"
git check-ignore -v <path> # a regra agora aparece Diagnostique, desrastreie, verifique. O padrão por trás de todo relato de “gitignore não funciona” é o mesmo arquivo com dois chapéus — rastreado de um lado do índice, ignorado do outro — e um flag --cached tira o segundo chapéu.
FAQ
Por que o .gitignore não funciona?
Na maioria dos casos o arquivo já está rastreado. O git só ignora arquivos não rastreados; um arquivo no índice é imune ao .gitignore até você tirá-lo do rastreamento com git rm --cached e commitar.
Como verificar qual regra do gitignore casa com um arquivo?
Rode git check-ignore -v <path>. Ele imprime a linha exata do .gitignore e o número da regra, ou sai em silêncio quando o arquivo está rastreado e nenhuma regra se aplica.
O git rm --cached apaga o meu arquivo local?
Não. O --cached remove o arquivo apenas do índice; a cópia em disco permanece. Commite a remoção e o arquivo vira não rastreado, e aí o .gitignore passa a valer.
Por que o gitignore não consegue re-incluir um arquivo dentro de uma pasta ignorada?
Por desempenho, o git pula diretórios excluídos por inteiro. Segundo a documentação do git, é impossível re-incluir um arquivo se um diretório pai dele estiver excluído.
— mrsaynothing
Get the next one by email
One email per post. No spam, no algorithms.
what is this?Ollama não usa a GPU? Corrija no Linux, Windows e WSL
Gostou dos artigos? É assim que eu construo profissionalmente. me contrate