Excluir ramificações locais do Git após excluí-las no repositório remoto

162

Quero ter meus repositórios locais e remotos sempre sincronizados em termos de ramificações.

Após uma revisão de solicitação de recebimento no GitHub, mesclo e removo minha ramificação (remota). Como eu poderia buscar essas informações no meu repositório local e pedir ao Git para remover minha versão local da ramificação também?

sf89
fonte
Deseja excluir suas filiais de rastreamento remoto, filiais locais ou ambas? Na verdade, você pode escrever um alias (bash ou git) que terá todas as ramificações remotas excluídas e também encontrará cópias locais para excluir, tudo em um comando.
Talvez tente usar os seguintes comandos para criar algo, git ls-remotee git show-ref.
Além disso, você pode querer conferir git symbolic-refe git update-ref.
obrigado por sua ajuda, acabei encontrando a resposta em outro lugar. Veja minha resposta.
Sf89
3
Possível duplicata Retire os ramos não está mais no controle remoto
amaechler

Respostas:

180

A maneira rápida

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

NB: se você não estiver ativo master, isso pode excluir o ramo. Continue lendo para o "caminho melhor".

Certifique-se de manter o mestre

Você pode garantir que master, ou qualquer outra ramificação nesse sentido, não seja removida por grepmais. Nesse caso, você iria:

git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d

Então, se quiséssemos manter master, develope stagingpor exemplo, iríamos:

git branch --merged | grep -v "\*" | grep -Ev "(\*|master|develop|staging)" | xargs -n 1 git branch -d

Tornar este um alias

Como é um pouco longo, convém adicionar um alias ao seu .zshrcou .bashrc. O meu é chamado gbpurge(para git branches purge):

alias gbpurge='git branch --merged | grep -Ev "(\*|master|develop|staging)" | xargs -n 1 git branch -d'

Em seguida, recarregue seu .bashrcou .zshrc:

. ~/.bashrc

ou

. ~/.zshrc
sf89
fonte
Você pode colocar os comandos em um alias e transformá-lo em um único comando. No entanto, como branché um comando de porcelana e não um encanamento , preste atenção às alterações na interface do usuário nas versões futuras do Git que possam quebrá-lo.
1
Perfeito! Observe que, após o fluxo de trabalho do Github, a ramificação local masterserá excluída.
Rubens Mariuzzo
Não, com certeza ele fica lá (eu estou usando todos os dias e parece que não faz isso).
sf89
4
FYI, se você quiser manter várias ramificações você pode usar um único grep, assim: grep -Ev '(\*|master|important-branch)'
Andrew Burns,
4
Se você deseja colocar isso no seu ~/.gitconfiglugar, adicione o seguinte à [alias]seção: gbpurge = !"git branch --merged | grep -Ev '\\*|master|develop|staging' | xargs -n 1 git branch -d"(não é necessário usar () na expressão grep).
dskrvk
82

Eu uso o mesmo fluxo com o GitHub e não achei as respostas anteriores me satisfazendo, pois git branch --mergedlista ramos que foram mesclados, mas nem todos foram removidos remotamente no meu caso. Então, isso funcionou para mim:

git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d

Onde:

  • git fetch --all -p: atualizar o status das filiais locais
  • git branch -vv: lista o status das filiais locais
  • grep ": gone]": filtrar os excluídos
  • awk '{ print $1 }': extrair seus nomes
  • xargs -n 1 git branch -d: passe o nome para o comando delete

Nota: se preferir, você pode usar -D em vez de -d, o que impõe a exclusão.

Por exemplo:

someUsr@someHost:~/repo$ git branch -a
basic-testing
integration-for-tests
* master
origin
playground-for-tests
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

someUsr@someHost:~/repo$ git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d
Fetching origin
Deleted branch integration-for-tests (was fbc609a).
Deleted branch playground-for-tests (was 584b900).

someUsr@someHost:~/repo$ git branch -a
basic-testing
* master
origin
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

Referência:

http://git-scm.com/book/en/v2/Git-Branching-Remote-Branches

Alessio
fonte
3
Tomei a liberdade para garantir que eu sempre vou fazer isso contra mestre, portanto: git checkout master; git pull origin master; git fetch --all -p; git branch -vv | grep gone | awk '{ print $1 }' | xargs -n 1 git branch -d Grande roteiro e explicação, obrigado por que :)
Miguelgraz
Observe que branch -vvmostra a última mensagem de confirmação da ramificação. Se você tivesse "ido" nessa mensagem, grep gonetambém atingiria esse ramo. Portanto, grep ": gone]"é provavelmente um pouco mais seguro de usar.
precisa saber é o seguinte
1
Esta é a resposta real à pergunta. Obrigado.
Andrei Gladkyi
1
Ainda melhor:awk '$3 $4 ~ /:gone]$/ { print $1 }'
Jakub Bochenski
3
Além de precisar, em -Dvez -ddisso, é a resposta perfeita!
Cas
72

experimentar:

git pull --prune

que exclui sua ramificação local, se a ramificação remota correspondente for excluída.

Atualizada:

A afirmação acima não está correta.

Na verdade, a execução git pull --pruneserá só remover os ramos-monitoramento remoto , tais como

controles remotos / origem / fff
controles remotos / origem / dev
controles remotos / origem / mestre

Em seguida, você pode executar git branch -rpara verificar as ramificações de rastreamento remoto deixadas em sua máquina. Suponha que os ramos esquerdos sejam:

origem / dev
origem / mestre

o que significa que o ramo origin/fffé excluído.

Então, depois de executar git pull --prune, basta executar:

git branch --merged | grep -vFf <(git branch -r | cut -d'/' -f2-)

você pode descobrir todas as filiais locais que:

  1. não tem mais ramificações remotas correspodificadas;
  2. pode ser removido com segurança.

então, <the command above> | xargs git branch -dpode excluir todos eles.

nicky_zs
fonte
42
Essa resposta não está correta. O --prunesinalizador excluirá apenas ramificações de rastreamento remoto, não ramificações locais.
3
De acordo com o @Cupcake aqui, isso não alcança o que estou procurando aqui.
Sf89
6
Não vou votar, mas é isso que eu precisava depois de excluir as ramificações locais e depois excluir o GitHub, mas elas ainda existem como controles remotos no meu comando git remote -v.
Spechal
8
Você também pode fazer git fetch --prune, essa é a minha maneira de escolha
e_m0ney
1
No entanto, outro erro do Git nos conselhos encontrados no estouro de pilha ... git pull --pruneresultou em "Você pediu para extrair do '--prune' remoto, mas não especificou uma ramificação. Como esse não é o controle remoto padrão configurado para sua ramificação atual, você deve especificar uma ramificação na linha de comando ".
JWW
23

Isso deve funcionar para evitar a exclusão dos ramos mestre e de desenvolvimento com a solução aceita:

git branch --merged | egrep -v "^\*|master|development" | xargs -n 1 git branch -d
Intrépido
fonte
16

Para pessoas que usam o PowerShell, isso é equivalente à resposta acima :

git branch -vv | Select-String -Pattern ': gone]' | ForEach-Object{($_ -split "\s+")[1]} | %{ git branch -D $_ }
  1. Filtre todos os ramos que estão marcados como desaparecidos
  2. Chame git branch -Dcada uma das ramificações encontradas
amaechler
fonte
6

Nada disso estava funcionando para mim. Você pode ver minha outra resposta aqui: https://stackoverflow.com/a/34969726/550454

Mas, essencialmente, agora tenho isso no meu ~/.gitconfig:

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -d
Karl Wilbur
fonte
5

Solução muito simples: remova seu repositório local e clone novamente o remoto. Pode não parecer muito elegante, mas é simples e você entenderá exatamente o que está fazendo sem ler as páginas de manual :-).


fonte
1
Por que tantos votos negativos? Quero dizer, obviamente, não é eficiente, especialmente com acordos de recompra maiores, mas faz o que o OP pediu. Existe alguma outra razão para não fazer isso?
3ocene
6
Porque você perderá todas as suas filiais locais, esconderijos, commits sem pressão ... é como pescar com dinamite.
sevenseacat
1
O mesmo acontece quando o laptop em que você está trabalhando, de alguma forma, é corrompido, perdido ou roubado, então eu não costumo manter nada crucial localmente. Parece-me melhor criar um ramo e enviá-lo, mesmo para pequenos recursos, e excluí-lo depois que ele não for mais útil.
1

Eu escrevi este one-liner para listar todos os ramos locais que não têm ramo remoto correspondente:

diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -

Depois disso, é fácil excluir essas ramificações locais com xargs:

diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -|xargs -r git branch -d
ks1322
fonte
isso também está listado master, não funciona como esperado; seja cuidadoso
Enrico
1

Eu apenas faço isso para remover as ramificações locais mescladas:

git branch -d $(git branch --merged)

e caso você queira remover rastreamentos inexistentes também:

git pull --prune
alacambra
fonte
1

Se você acabou de enviar e mesclar sua ramificação para master, faça o seguinte no git bash:

git branch -d branch_name_to_delete

Se você estiver nesse ramo, ele o levará de volta ao mestre. Neste ponto, faça um puxão com

git pull
Joshua Schlichting
fonte
-2

A resposta votada tem o potencial de excluir o mestre. Considere o exemplo prático abaixo.

Eu tinha dois ramos de recursos hemen_README e hemen_BASEBOX que foram mesclados no desenvolvimento e, em seguida, o desenvolvimento foi mesclado no mestre. Os ramos do recurso hemen_README e hemen_BASEBOX foram excluídos remotamente, mas ainda estavam aparecendo localmente. Também não estou no mestre localmente, mas no desenvolvimento.

Nesse caso

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
    * develop                      671ad6c Merged in hemen_README (pull request #1)
        hemen_BASEBOX                a535c0f added global exec paths to puppet manifest
        hemen_README                 ba87489 Updated Readme with considerable details
        master                       8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
        remotes/origin/develop       671ad6c Merged in hemen_README (pull request #1)
        remotes/origin/hemen_BASEBOX a535c0f added global exec paths to puppet manifest
        remotes/origin/hemen_README  ba87489 Updated Readme with considerable details
        remotes/origin/master        2f093ce Merged in develop (pull request #3)

Então, se eu executar o comando parcial acima

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch --merged | grep -v "\*"
        hemen_BASEBOX
        hemen_README
        master

Observe que ele também mostra o mestre, que será excluído.

De qualquer forma, eu consegui. Estou compartilhando meu log de sessão com você sobre como consegui isso.

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git remote prune origin --dry-run
    Pruning origin
    URL: [email protected]:hemenkapadiapublic/vagrant-webdev.git
     * [would prune] origin/hemen_BASEBOX
     * [would prune] origin/hemen_README
    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git remote prune origin 
    Pruning origin
    URL: [email protected]:hemenkapadiapublic/vagrant-webdev.git
     * [pruned] origin/hemen_BASEBOX
     * [pruned] origin/hemen_README

Acabei de verificar o que será podado e depois podado. olhando para o comando branch abaixo, cuidamos dos controles remotos

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
    * develop                671ad6c Merged in hemen_README (pull request #1)
        hemen_BASEBOX          a535c0f added global exec paths to puppet manifest
        hemen_README           ba87489 Updated Readme with considerable details
        master                 8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
        remotes/origin/develop 671ad6c Merged in hemen_README (pull request #1)
        remotes/origin/master  2f093ce Merged in develop (pull request #3)

Agora vá em frente e exclua filiais locais

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -d hemen_BASEBOX 
    Deleted branch hemen_BASEBOX (was a535c0f).
    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -d hemen_README
    Deleted branch hemen_README (was ba87489).

Bom agora os galhos são como desejado.

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
    * develop                671ad6c Merged in hemen_README (pull request #1)
        master                 8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
        remotes/origin/develop 671ad6c Merged in hemen_README (pull request #1)
        remotes/origin/master  2f093ce Merged in develop (pull request #3)
Hemen Kapadia
fonte
Claro que tem o potencial de excluir o mestre. Por favor, leia a pergunta com atenção. Como eu disse lá, eu precisava de uma maneira de limpar as coisas no meu local. Isso significa excluir todas as ramificações que não existem mais no controle remoto. Se o mestre não estiver mais lá, ele também desaparecerá na sua máquina local.
Sf89