Existe uma maneira simples de excluir todas as ramificações de rastreamento cujo equivalente remoto não existe mais?
Exemplo:
Ramos (local e remoto)
- mestre
- origem / mestre
- origem / bug-fix-a
- origem / bug-fix-b
- origem / bug-fix-c
Localmente, eu só tenho uma filial principal. Agora eu preciso trabalhar no bug-fix-a , para que eu faça check-out, trabalhe nele e transfira as alterações para o controle remoto. Em seguida, faço o mesmo com o bug-fix-b .
Ramos (local e remoto)
- mestre
- bug-fix-a
- bug-fix-b
- origem / mestre
- origem / bug-fix-a
- origem / bug-fix-b
- origem / bug-fix-c
Agora eu tenho ramificações locais master , bug-fix-a , bug-fix-b . O mantenedor da ramificação mestre mesclará minhas alterações no mestre e excluirá todas as ramificações que ele já mesclou.
Portanto, o estado atual é agora:
Ramos (local e remoto)
- mestre
- bug-fix-a
- bug-fix-b
- origem / mestre
- origem / bug-fix-c
Agora eu gostaria de chamar algum comando para excluir as ramificações (neste caso, bug-fix-a , bug-fix-b ), que não são mais representadas no repositório remoto.
Seria algo como o comando existente git remote prune origin
, mas mais parecido git local prune origin
.
fonte
* master
no meu sistema. O seguinte comando funcionou para mim:git branch -d $(git branch --merged |tail -n +2)
develop
entãogit branch --merged
incluimaster
! Você provavelmente (definitivamente!) Não quer excluir isso. Também acho que deveria sergit branch -d
onde minúsculas-d
significa "exclusão segura", por exemplo, somente exclusão se mesclada.git branch --merged | grep -v "master" >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
Após o comando
remove as referências remotas quando você executa
mostrará 'ido' como o status remoto. Por exemplo,
Portanto, você pode escrever um script simples para remover ramificações locais remotas:
Observe que o acima usa o comando "porcelain"
git branch
para obter o status upstream.Outra maneira de obter esse status é usar o comando "encanamento"
git for-each-ref
com a variável de interpolação%(upstream:track)
, que será[gone]
exatamente como acima.Essa abordagem é um pouco mais segura, porque não há risco de correspondência acidental em parte da mensagem de confirmação.
fonte
git branch -vv | gawk '{print $1,$4}' | grep 'gone]' | gawk '{print $1}'
awk '/: gone]/{if ($1!="*") print $1}'
. Isso agora funciona como esperado.test = "!git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done"
A maioria dessas respostas não responde à pergunta original. Fiz várias escavações e essa foi a solução mais limpa que encontrei. Aqui está uma versão um pouco mais completa dessa resposta:
git checkout master
git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d
Explicação:
Funciona removendo seus desvios de rastreamento e excluindo os locais que mostram que eles "desapareceram"
git branch -vv
.Notas:
Se o seu idioma estiver definido como algo diferente do inglês, você precisará mudar
gone
para a palavra apropriada. Ramos que são apenas locais não serão tocados. As ramificações que foram excluídas no controle remoto, mas não foram mescladas, mostrarão uma notificação, mas não serão excluídas no local. Se você deseja excluí-los, mude-d
para-D
.fonte
git checkout master && ...
no início do comando.git branch -vv
começará com um asterisco que acabará resultando na execuçãogit branch -d *
. Aqui está uma versão corrigida que irá ignorar linhas com asterisco:git branch -vv | grep ': gone]'| grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d
Normalmente, eu não responderia a uma pergunta que já tem 16 respostas, mas todas as outras respostas estão erradas e a resposta certa é muito simples. A pergunta diz: "Existe uma maneira simples de excluir todas as ramificações de rastreamento cujo equivalente remoto não existe mais?"
Se "simples" significa excluir todos eles de uma só vez, não frágeis, não perigosos e sem depender de ferramentas que nem todos os leitores terão, a resposta certa é: não.
Algumas respostas são simples, mas elas não fazem o que foi solicitado. Outros fazem o que foi solicitado, mas não são simples: todos contam com a análise da saída do Git por meio de comandos de manipulação de texto ou linguagens de script, que podem não estar presentes em todos os sistemas. Além disso, a maioria das sugestões usa comandos de porcelana, cuja saída não é projetada para ser analisada por script ("porcelana" refere-se aos comandos destinados à operação humana; os scripts devem usar os comandos "encanamento" de nível inferior).
Leitura adicional:
git branch
saída em um script .git remote prune
,git prune
,git fetch --prune
Se você quiser fazer isso com segurança, no caso de uso em questão (ramificações de rastreamento de coleta de lixo que foram excluídas no servidor, mas ainda existem como ramificações locais) e apenas com comandos de alto nível Git, é necessário
git fetch --prune
(ougit fetch -p
, que é um alias, ougit prune remote origin
que faz a mesma coisa sem buscar e provavelmente não é o que você deseja na maioria das vezes).git branch -v
(qualquer ramo de rastreamento órfão será marcado como "[foi]").git branch -d [branch_name]
em cada ramo de rastreamento órfão(que é o que algumas das outras respostas propõem).
Se você deseja criar um script para uma solução, então
for-each-ref
é o seu ponto de partida, como na resposta de Mark Longair aqui e nesta resposta a outra pergunta , mas não consigo encontrar uma maneira de explorá-la sem escrever um loop de script de shell ou usar xargs ou algo assim .Explicação em segundo plano
Para entender o que está acontecendo, você precisa entender que, na situação de rastrear ramificações, você não tem uma ramificação, mas três. (E lembre-se de que "ramificação" significa simplesmente um ponteiro para uma confirmação.)
Dada uma ramificação de rastreamento
feature/X
, o repositório remoto (servidor) terá essa ramificação e a chamaráfeature/X
. Seu repositório local possui uma ramificaçãoremotes/origin/feature/X
que significa "Isso foi o que o controle remoto me disse sobre sua ramificação de recursos / X, da última vez que conversamos" e, finalmente, o repositório local possui uma ramificaçãofeature/X
que aponta para sua confirmação mais recente e está configurada para "track"remotes/origin/feature/X
, o que significa que você pode puxar e empurrar para mantê-los alinhados.Em algum momento, alguém excluiu
feature/X
o controle remoto. A partir desse momento, você fica com o seu localfeature/X
(o que provavelmente não quer mais, pois o trabalho no recurso X provavelmente está concluído) e o seuremotes/origin/feature/X
com certeza é inútil, pois seu único objetivo era lembrar o estado da ramificação do servidor .E o Git permitirá que você limpe automaticamente os redundantes
remotes/origin/feature/X
- é o quegit fetch --prune
faz - mas, por algum motivo, ele não exclui automaticamente os seusfeature/X
... mesmo que vocêfeature/X
ainda contenha as informações de rastreamento órfãs, ele tem as informações para identificar ramificações de rastreamento anteriores que foram totalmente mescladas. (Afinal, ele pode dar -lhe a informação que lhe permite fazer a operação com a mão mesmo.)fonte
xargs
). Também hágit alias
para simplificar vários casos.xargs
bash, e provavelmente não estão aqui procurando um desafio de microcodificação, tanto quanto uma resposta rápida que podem ser aplicados com segurança sem se distrair do objetivo real .Encontrei a resposta aqui: Como posso excluir todos os ramos git que foram mesclados?
Certifique-se de manter o mestre
Você pode garantir que
master
, ou qualquer outra ramificação, não seja removida adicionando outragrep
após a primeira. Nesse caso, você iria:Então, se quiséssemos manter
master
,develop
estaging
por exemplo, iríamos:Tornar este um alias
Como é um pouco longo, convém adicionar um alias ao seu
.zshrc
ou.bashrc
. O meu é chamadogbpurge
(paragit branches purge
):Em seguida, recarregue seu
.bashrc
ou.zshrc
:ou
fonte
Solução Windows
Para o Microsoft Windows Powershell:
git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}
Explicação
git checkout master
muda para o ramo principalgit remote update origin --prune
ameixas ramos remotosgit branch -vv
obtém uma saída detalhada de todos os ramos ( referência do git )Select-String -Pattern ": gone]"
obtém apenas os registros de onde foram removidos do controle remoto.% { $_.toString().Trim().Split(" ")[0]}
obter o nome do ramo% {git branch -d $_}
exclui a ramificaçãofonte
.Trim()
depois.toString()
para remover dois espaços antes do nome do ramo.git branch -d
para paragit branch -D
mais eu recebo o erro que o ramo não está totalmente mesclado.git branch -D
é destrutivo e excluirá o trabalho local que você ainda não enviou.-d
é sempre seguro, apenas tenha cuidado-D
.A correspondência de padrões para "ido" na maioria das outras soluções foi um pouco assustadora para mim. Para ser mais seguro, isso usa o
--format
sinalizador para retirar o status de rastreamento upstream de cada filial .Eu precisava de uma versão compatível com o Windows, portanto, isso exclui todos os ramos listados como "desaparecidos" usando o Powershell:
A primeira linha lista o nome das ramificações locais cuja ramificação upstream está "ausente". A próxima linha remove as linhas em branco (que são enviadas para as ramificações que não desapareceram) e o nome da ramificação é passado ao comando para excluir a ramificação.
fonte
--format
opção parece ser bastante nova; Eu precisava atualizar o git de 2.10.something para 2.16.3 para obtê-lo. Esta é a minha modificação para sistemas Linux-ish:git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" | sed 's,^refs/heads/,,' | grep . | xargs git branch -D
refname:short
. Então você pode excluir a linha% { $_ -replace '^refs/heads/', '' }
git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | where { $_ -ne "" } | foreach { git branch -d $_ }
Provavelmente também é uma boa idéia usar em-d
vez de-D
. A exclusão forçada não deve ser necessária para ramificações que não estão mais no controle remoto.Remova todas as ramificações que foram mescladas no mestre, mas não tente remover o próprio mestre:
git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)
ou adicione um alias:
alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"
Explicação:
git checkout master
ramo mestre de checkoutgit pull origin master
garantir que a filial local tenha todas as alterações remotas mescladasgit fetch -p
remova referências a ramificações remotas que foram excluídasgit branch -d $(git branch master --merged | grep master -v)
exclua todas as ramificações que foram mescladas no mestre, mas não tente remover o próprio mestrefonte
git branch -D
comandogit branch -d
que deve emitir um aviso sobre ramos não enviados .Isso removerá todos os ramos que não existem mais no controle remoto.
fonte
X
; vocêgit checkout X
; agora seu repositório possui uma ramificação de rastreamento (local)X
e uma ramificação remotaorigin/X
; o repositório remoto excluiX
; vocêgit fetch-p
; no seu repositório local, não apenasorigin/X
mas tambémX
foram excluídos. É isso que você está dizendo?Mais uma resposta para a pilha, baseando-se fortemente na resposta de Patrick (que eu gosto porque parece acabar com qualquer ambiguidade sobre onde
gone]
será a correspondência nagit branch
saída), mas adicionando uma * nix dobrada.Na sua forma mais simples:
Eu tenho isso embrulhado em um
git-gone
script no meu caminho:NB - A
--format
opção parece ser relativamente nova; Eu precisava atualizar o git de 2.10.something para 2.16.3 para obtê-lo.EDIT: tweaked para incluir sugestão sobre
refname:short
de Benjamin W.NB2 - Eu só testei
bash
, daí o hashbang, mas provavelmente portátilsh
.fonte
sed
parte usando%(refname:short)
na primeira linha?--format
. Outra maneira de pular ased
peça é usargit update-ref -d
. Observe que isso provavelmente é um tanto perigoso, o usogit for-each-ref
é mais seguro aqui (fornecido--shell
).--format
isso. Apenas uma pergunta: por que o#!bash
? Tudo aqui parece portátilsh
para mim.Pode ser útil para alguns, uma linha simples para limpar todos os ramos locais, exceto o mestre e o desenvolvimento
fonte
'git branch | grep -v "master" | grep -v "develop"
tipo de coisa antes de se comprometer a adicionar a parte de exclusão do comando. FinIsso excluirá todo o ramificado local mesclado, exceto a referência mestre local e o que está sendo usado atualmente:
E isso excluirá todos os ramos que já foram removidos do repositório remoto referenciado por " origem ", mas ainda estão disponíveis localmente em " controles remotos / origem ".
fonte
git branch -vv | grep 'gone]' | grep -v "\*" | awk '{print $1}' | xargs -r git branch -d
Explicação: Prefiro substituirgit branch --merged
by porgit branch -vv
para mostrar o status (desaparecido) porque o anteriorgit branch --merged
também pode mostrar o mestreEu não acho que exista um comando interno para fazer isso, mas é seguro fazer o seguinte:
Quando você usa
-d
, o git se recusa a excluir a ramificação, a menos que ela seja completamente mescladaHEAD
ou sua ramificação de rastreamento remoto upstream. Portanto, você sempre pode fazer um loop sobre a saídagit for-each-ref
e tentar excluir cada ramificação. O problema com essa abordagem é que eu suspeito que você provavelmente não desejabug-fix-d
ser excluído apenas porqueorigin/bug-fix-d
contém seu histórico. Em vez disso, você pode criar um script parecido com o seguinte:Aviso: não testei esse script - use apenas com cuidado ...
fonte
TL; DR:
Remova TODAS as ramificações locais que não estão no controle remoto
Remova TODAS as ramificações locais que não estão no remoto E que estão totalmente mescladas E que não são usadas como dito em muitas respostas anteriores.
Explicação
git fetch -p
podará todas as ramificações que não existem mais no controle remotogit branch -vv
imprimirá galhos locais e galhos podados serão marcados comgone
grep ': gone]'
seleciona apenas o ramo que se foiawk '{print $1}'
filtre a saída para exibir apenas o nome das ramificaçõesxargs git branch -D
irá percorrer todas as linhas (ramificações) e forçar a remover essa ramificaçãoPor que
git branch -D
e nãogit branch -d
mais você terá para ramos que não são totalmente mesclados.fonte
Você poderia fazer isso:
fonte
Com base nas informações acima, isso funcionou para mim:
Ele remove todas as ramificações locais com estão
': gone] '
no controle remoto.fonte
gone
qualquer lugar em seu nome.O comando acima pode ser usado para buscar ramificações que são mescladas e excluídas no controle remoto e exclui o ramo local que não está mais disponível no controle remoto
fonte
grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -D
para forçar a excluir tudo #gone
em qualquer lugar (por exemplousingonefunction
).Nada disso foi realmente certo para mim. Eu queria algo que limpasse todas as ramificações locais que estavam rastreando uma ramificação remota
origin
, onde o ramo remoto foi excluído (gone
). Eu não queria excluir ramificações locais que nunca foram configuradas para rastrear uma ramificação remota (ou seja: minhas ramificações locais de desenvolvimento). Também queria um one-liner simples que apenas usassegit
, ou outras ferramentas CLI simples, em vez de escrever scripts personalizados. Acabei usando um pouco degrep
eawk
para fazer esse comando simples.Isso foi o que acabou no meu
~/.gitconfig
:Aqui está um
git config --global ...
comando para adicionar isso facilmente comogit prune-branches
:NOTA: No comando config, eu uso a
-d
opção emgit branch
vez de-D
, como na minha configuração real. Uso-D
porque não quero ouvir o Git reclamar de galhos imersos. Você também pode querer essa funcionalidade. Nesse caso, basta usar em-D
vez de-d
no final desse comando de configuração.fonte
git branch -vv
e saudar: gone]
e não fazergit branch -v
e saudar[gone]
?v
. Segit branch -v | grep '[gone]'
funcionar para você, vá em frente. Parece um pouco mais limpo.Baseado na dica do Git: Excluindo ramificações locais antigas , que se parece com a solução de jason.rickman, implementei um comando personalizado para esse propósito, chamado git, usando o Bash:
git gone -pn
combina a poda e lista os ramos "desaparecidos":Então você pode puxar o gatilho usando
git gone -d
ougit gone -D
.Notas
"$BRANCH/.*: gone]"
onde$BRANCH
normalmente estariaorigin
. Provavelmente isso não funcionará se a saída do Git estiver localizada em francês etc.fonte
git gone
parece um apelido paragit branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d
, que resolve o problema do OP.Baseando-se fortemente a partir de um número de outras respostas aqui, eu acabei com o seguinte (git 2,13 e acima só, creio), que deve funcionar em qualquer UNIX-like shell:
Isso notavelmente usa em
for-each-ref
vez debranch
(comobranch
é um comando "porcelana" projetado para saída legível por humanos, não para processamento de máquina) e usa seu--shell
argumento para obter uma saída de escape adequada (isso nos permite não nos preocupar com nenhum caractere no nome ref).fonte
[ ! -z "$ref" ]
significa. Eu acho que um multi-liner já teria ajudado. Mas ainda obrigado pela sua contribuição!Outra resposta, porque nenhuma das soluções atende às minhas necessidades de elegância e plataforma cruzada:
Comando para excluir filiais locais que não estão no controle remoto:
Para integrá-lo ao gitconfig para que ele possa ser executado com
git branch-prune
:Bater
PowerShell
(Precisa de ajuda para encontrar um comando universal para o PowerShell e o bash)
Por que essa resposta é a melhor?
git branch-prune
comando ao seu gitgit for-each-ref
--filter
sem que sejam necessárias dependências externasExplicação:
~\.gitconfig
. Depois de executar isso, você pode simplesmente fazergit branch-prune
--prune
bandeira, que "remove as ramificações de rastreamento remoto que não estão mais no controle remoto"git for-each-ref
e--filter
, para obter uma lista dos ramos são[gone]
(sem controle remoto)fonte
Eu vim com esse script bash. É sempre manter os ramos
develop
,qa
,master
.fonte
Eu uso um método curto para fazer o truque, eu recomendo que você faça o mesmo, pois isso pode economizar algumas horas e dar mais visibilidade
Basta adicionar o seguinte trecho ao seu .bashrc (.bashprofile no macos).
Você precisará editar a regex grep para atender às suas necessidades (aqui, isso impede a exclusão de master, preprod e dmz)
fonte
git fetch --all --prune
fez o truque. Obrigado!Isso funcionou para mim:
fonte
Não sei por quanto tempo, mas agora uso o git-up, que cuida disso.
eu faço
git up
e ele começa a rastrear novas ramificações e excluir as antigas.Apenas para deixar claro, não é um comando git pronto para uso - https://github.com/aanand/git-up
BTW também esconde árvore suja e faz rebotes ainda com apenas
git up
.Espero que seja útil para alguém
fonte
Aqui está uma solução que eu uso para a casca do peixe. Testado em
Mac OS X 10.11.5
,fish 2.3.0
egit 2.8.3
.Algumas notas:
Certifique-se de definir o correto
base_branch
. Nesse caso, eu usodevelop
como o ramo base, mas pode ser qualquer coisa.Esta parte é muito importante:
grep -v "\(master\|$base_branch\|\*\)"
. Ele garante que você não exclua o mestre ou sua filial base.Uso
git branch -d <branch>
como precaução extra, para não excluir nenhum ramo que não tenha sido totalmente mesclado ao HEAD upstream ou atual.Uma maneira fácil de testar é substituir
git branch -d $f
porecho "will delete $f"
.Suponho que devo acrescentar: USE POR SEU PRÓPRIO RISCO!
fonte
Eu escrevi um script Python usando o GitPython para excluir ramificações locais que não existem no controle remoto.
Espero que alguém ache útil, por favor, adicione comentários se eu perdi alguma coisa.
fonte
Se você estiver usando o
zsh
shell com oOh My Zsh
instalado, a maneira mais fácil de fazer isso com segurança é usar o preenchimento automático embutido.Primeiro, determine com quais ramificações você deseja excluir:
isso mostrará uma lista de ramos já mesclados
Depois de conhecer alguns que deseja excluir, digite:
Tudo o que você precisa fazer é clicar em [tab] e ele exibirá uma lista dos ramos locais. Use tab-complete ou apenas pressione [tab] novamente e você pode alternar entre eles para selecionar um ramo com [enter].
Guia Selecione os ramos repetidamente até ter uma lista dos ramos que deseja excluir:
Agora basta pressionar Enter para excluir sua coleção de filiais.
Se você não estiver usando o zsh no seu terminal ... Obtenha aqui.
fonte
Eu gosto de usar pipes porque facilita a leitura do comando.
Esta é a minha solução se você deseja remover todos os ramos, exceto o mestre.
Para excluir outras ramificações que correspondem aos seus critérios, modifique o primeiro e o segundo bloco.
fonte
Aqui está a resposta simples que funcionou para mim usando um cliente git:
Exclua completamente o repositório da sua máquina e faça o check-out novamente.
Não mexa com scripts arriscados.
fonte