Um WordPress que atendo tinha o repositório versionando a instalação inteira: núcleo do WordPress, plugins de terceiros, traduções, tudo dentro do Git. Depois de uma atualização do WP, o git status mostrou 225 arquivos untracked de uma vez só, mas o problema maior era o histórico, que carregava um diff morto de quase 2,5 milhões de linhas — commits de atualização de plugin que ninguém ia revisar nunca. Por isso, a régua que apliquei ali, e uso hoje em todo projeto WordPress, é simples: o repositório versiona só o que é meu. Depois de reescrever o .gitignore, saíram do repo cerca de 11 mil arquivos que nunca deveriam ter entrado.
O que é seu e o que não é
Regra prática: se você não edita aquele código, ele não é seu. Ou seja, núcleo do WordPress, plugins de terceiros (mesmo os pagos), temas de terceiros e arquivos de tradução são atualizados pelo wp-admin ou por um gerenciador de dependência — nunca por um commit seu. Nesse sentido, o que entra no repositório é o tema próprio, os plugins que você escreveu e os assets que fazem parte do seu build. Mas o resto o deploy nem toca.
O .gitignore em whitelist
De fato, a forma que funciona sem exceção pra mim é inverter a lógica: em vez de listar tudo que quero fora, eu ignoro tudo por padrão e libero só o que é meu.
O detalhe que pega todo mundo na primeira vez: o Git não desce em diretório ignorado. Pois, pra liberar uma pasta funda, é preciso reabrir cada nível — !/wp-content/ primeiro, depois /wp-content/* pra ignorar o conteúdo de novo, e só então !/wp-content/themes/meu-tema/ pra liberar a pasta que interessa. Por isso, pular um nível e a exceção simplesmente não pega.
Por que isso importa (não é só estética)
Migrando um repositório que já versiona tudo
Portanto, o git status fica limpo e o histórico para de ganhar ruído a cada atualização de plugin.
Bônus: travando arquivo sensível no CI
Depois de arrumar o .gitignore, adicionei um passo no CI que falha o PR se aparecer um arquivo sensível versionado — wp-config.php, .sql, .log, .pem. Além disso, é pouca configuração e evita que uma credencial vá parar num commit por descuido.
Em todo o caso, isso não substitui o .gitignore: é uma segunda trava, para o caso de alguém forçar um git add -f.