CLI AI

Exclua todas as branches locais mescladas no git

2026-07-02

git branch --merged main | grep -vE '^\*|main|develop' | xargs -r git branch -d exclui toda branch local já mesclada na main, exceto main e develop. Ele não vai tocar nas branches mescladas por squash: o git nunca registra os commits delas como mesclados, então o --merged nunca as vê — para essas, confira o git branch -vv procurando a marca gone.

1. Primeiro veja o que conta como mesclado

clai
$ clai mostre as branches mescladas na main→ git branch --merged main  feature-merged* main

É uma lista somente leitura. A branch atual é marcada com um asterisco e não pode ser excluída — nem precisa.

2. Exclua, mas proteja as branches principais

clai
$ clai exclua as branches locais mescladas na main, exceto main e develop→ git branch --merged main | grep -vE '^\*|main|develop' | xargs -r git branch -dDeleted branch feature-merged (was fb52fec).

-d é seguro: o git se recusa a excluir uma branch com commits não mesclados. O filtro grep -vE é obrigatório, senão a própria main entra na lista. O -r evita que o xargs rode quando a lista está vazia.

3. Confirme que nada importante foi excluído

clai
$ clai mostre as branches restantes→ git branch  feature-open* main

feature-open ainda tem commits não mesclados e permaneceu no lugar. Essa é a confirmação de que o filtro funcionou direito.

4. A armadilha: o squash merge se esconde do --merged

clai
$ clai mostre as branches cujo upstream foi excluído no servidor→ git fetch --prune && git branch -vv | grep '\[.*: gone\]'

Esta é a parte que importa. Um squash merge nunca leva os commits da branch para o histórico da main como estão, então o --merged nunca vai mostrá-la — ela fica na sua máquina para sempre. Mas o upstream dela no servidor some assim que o pull request é mesclado, e o git branch -vv marca essa branch como gone. Esse é o sinal confiável.

5. Exclua branches com upstream desaparecido

clai
$ clai exclua as branches locais cuja branch de origem foi excluída no servidor→ git fetch --prune && git branch --format '%(refname:short) %(upstream:track)' | awk '$2 == "[gone]" {print $1}' | xargs -r git branch -D⚠ CAUTION — this is -D, not -d: it also deletes unmerged branches

O -D é necessário justamente porque o git não considera mescladas as branches com squash merge, e recusa com -d. O preço: leia a lista do comando anterior antes de rodar este.

6. Limpe referências obsoletas do servidor

clai
$ clai remova referências a branches que não existem mais no servidor→ git remote prune origin

Isso só remove referências locais origin/* — não mexe nas suas branches. Útil quando o autocompletar continua sugerindo branches fechadas há seis meses.

Pegadinhas

  • -d e -D têm níveis de risco diferentes. A minúscula só exclui o que foi mesclado, a maiúscula exclui qualquer coisa. Branches com squash precisam da maiúscula, então primeiro liste, depois exclua.
  • --merged sem argumento conta a partir da branch atual. Parado numa branch de feature você recebe uma lista completamente diferente. Informe a base explicitamente: --merged main.
  • Excluir uma branch local não a exclui no servidor. Para isso é preciso git push origin --delete <nome>. E o contrário também: excluir no servidor não remove sua cópia local.

Perguntas relacionadas

Como recuperar uma branch que excluí sem querer? O git reflog mostra o último commit dela; depois git branch <nome> <hash>. Funciona até rodar o garbage collection.

Por que uma branch não é excluída? Ou você está nela — mude para a main — ou ela tem commits não mesclados e o -d está te protegendo de perdê-los.

Como vejo quando uma branch foi atualizada pela última vez? git branch --sort=-committerdate -v ordena por atualização — útil para achar as abandonadas.

Veja também

O CliAI transforma as frases acima no comando exato e o mostra antes de executar qualquer coisa — a etapa com -D recebe um rótulo CAUTION, não uma execução silenciosa. Instale em uma linha.