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 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 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 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 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 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 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
-de-Dtê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.--mergedsem 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
- Desfazer o último commit do git mantendo as alterações
- Remova um segredo do histórico do git
- Tarefas de git ditas em voz alta
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.