Voltar ao blog

Gitignore não funciona? A correção de verdade

17 de setembro de 2026

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 --cached acima.
  • Um .gitignore ausente 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 o git status do 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?

ArquivoEscopoCommitado?Usar para
.gitignore (repo)Todos que clonaremSimSaída de build, dependências, .env — regras compartilhadas
.git/info/excludeSó o seu cloneNãoBagunça pessoal: .scratch/, detritos de editor
core.excludesFile (global)Todos os seus repositóriosNãoLixo de SO: .DS_Store, Thumbs.db, *.swp
.gitignore + negaçãoRepositórioSimRe-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.

self-hosted · no third parties · one-click unsubscribe

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