Como posso excluir todos os ramos do Git que foram mesclados?

1936

Eu tenho muitos ramos do Git. Como excluo ramificações que já foram mescladas? Existe uma maneira fácil de excluir todos eles, em vez de excluí-los um por um?

Nyambaa
fonte
46
Ser um pouco mais específico git branch -Dexclui qualquer ramificação, mesclada ou não.
PhilT
12
Você também pode fazer isso diretamente no GitHub, se for para a seção 'branches' do seu repositório (por exemplo, github.com/<username>/<repo_name>/branches ). Deve haver uma lista de todos os seus ramos, com um ícone vermelho da lixeira no lado que excluirá o ramo selecionado. Muito mais rápido do que fazê-lo no terminal! Também mostrará o quão à frente / atrás de mastercada filial está. No entanto, seu cliente local ainda listará as ramificações antigas se você executar git branch -a; use git fetch --prunepara removê-los (conforme esta resposta ).
user5359531
3
Script para fazer isso localmente ou remotamente - com verificações de segurança e pré-configurados "ramos seguros": github.com/fatso83/dotfiles/tree/master/utils/... git delete-merged --doit origin ougit delete-merged --doit --local
oligofren
Você também pode usar este aplicativo para excluir automaticamente ramificações mescladas.
Sebass van Boxel 07/08/19
rm -fr work && git clone http://example.com/work.gitao longo dos anos tornou-se a maneira mais fácil de sair de um problema com o git.
Reactgular 19/04

Respostas:

3116

ATUALIZAR:

Você pode adicionar outros ramos para excluir como mestre e desenvolvedor, se o seu fluxo de trabalho tiver esses como um possível ancestral. Normalmente, eu ramifico uma tag "sprint-start" e o master, dev e qa não são ancestrais.

Primeiro, liste todas as ramificações que foram mescladas no controle remoto.

git branch --merged

Você pode ver alguns ramos que não deseja remover. podemos adicionar alguns argumentos para pular ramificações importantes que não queremos excluir como mestre ou um desenvolvimento. O comando a seguir pulará o branch master e qualquer coisa que tenha dev nele.

git branch --merged| egrep -v "(^\*|master|dev)"

Se você quiser pular, pode adicioná-lo ao comando egrep, como a seguir. A ramificação skip_branch_namenão será excluída.

git branch --merged| egrep -v "(^\*|master|dev|skip_branch_name)"

Para excluir todas as ramificações locais que já foram mescladas na ramificação com check-out atualmente:

git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d

Você pode ver que master e dev são excluídos caso sejam ancestrais.


Você pode excluir uma ramificação local mesclada com:

git branch -d branchname

Se não for mesclado, use:

git branch -D branchname

Para excluí-lo do uso remoto:

git push --delete origin branchname

git push origin :branchname    # for really old git

Depois de excluir a ramificação do controle remoto, você pode remover as ramificações de rastreamento remoto com:

git remote prune origin

ou podar ramificações de rastreamento remoto individuais, como a outra resposta sugere, com:

git branch -dr branchname

Espero que isto ajude.

Adam Dymitruk
fonte
46
AVISO: Se você acabou de criar uma ramificação, ela também será excluída. Certifique-se de não ter uma ramificação recém-criada na lista antes de executar o comando superior.
precisa
154
Oposto à advertência: o reflog salvará seu bacon. Então não se preocupe.
Adam Dymitruk 20/08/14
33
Lembre-se de que o primeiro comando exclui apenas ramificações locais, portanto, não é tão 'perigoso' como alguns apontaram.
ifightcrime
79
Variante do PowerShell, para que eu possa encontrá-lo aqui na próxima vez que pesquisar a resposta:git branch --merged | %{$_.trim()} | ?{$_ -notmatch 'develop' -and $_ -notmatch 'master'} | %{git branch -d $_}
vorou ​​20/12/2015
23
Isso gera um erro fatal: branch name requiredse você não tiver ramificações que devam ser excluídas. Para evitar que você possa passar -rpara xargs, ele não será executado git branch -dse o stdin estiver vazio. (Essa é uma extensão GNU xargs, de acordo com a página do manual).
Marius Gedminas
457

Para excluir todas as ramificações no controle remoto que já foram mescladas:

git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin

Nas versões mais recentes do Git

git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin

UPDATE (por @oliver; já que não cabe no comentário, mas já há respostas suficientes) : se você estiver no ramo ABC, o ABC aparecerá nos resultados de git branch -r --mergedporque o ramo não foi especificado, portanto, o padrão do ramo é o ramo atual e um ramo sempre se qualifica como mesclado consigo mesmo (porque não há diferenças entre um ramo e ele próprio!).

Então, especifique o ramo:

git branch -r --merged master | grep -v master ...

OU primeiro mestre de checkout:

git checkout master | git branch -r --merged | grep -v ...
kuboon
fonte
18
Melhor resposta de longe. Apenas uma nota, o meu branch master é nomeado deventão eu tive que mudar isso
Dorian
41
Eu tive que adicionar | grep origindepois grep -v masterpara evitar empurrar ramificações de outros controles remotos para a origem. Altamente recomendar testar a saída de antemão, usandogit branch -r --merged | grep -v master | grep origin | sed 's/origin\//:/' | xargs -n 1 echo
L0LN1NJ4
9
Modifiquei um pouco para excluir o developramo também. git branch -r --merged | grep -v master | grep -v develop | sed 's/origin\///' | xargs -n 1 git push --delete origin. Agora isso acabou sendo o meu apelido.
22415 sarat
8
O que fez dessa a melhor resposta que li foi o -rargumento, que não vi mencionado em nenhum outro lugar. É um dado adquirido que apenas as agências locais valem a pena fazer algumas tarefas domésticas. Mas os controles remotos também estão cheios de lixo.
Asbjørn Ulsberg 2/11
19
Cuidado - acabei de perceber: isso obviamente encontrará ramificações mescladas com a ramificação atual , não mestre, portanto, se você estiver myFeatureBranchnela, a limpeza será feita origin/myFeatureBranch. Provavelmente é melhor git checkout masterprimeiro.
jakub.g
190

Apenas estendendo um pouco a resposta de Adam:

Adicione isso à sua configuração do Git executando git config -e --global

[alias]
    cleanup = "!git branch --merged | grep  -v '\\*\\|master\\|develop' | xargs -n 1 git branch -d"

E então você pode excluir todas as ramificações mescladas locais de maneira simples git cleanup.

real_ate
fonte
11
não deveria ser o primeiro comando: git branch --merged mastercomo você deseja ver o que foi mesclado no mestre, o ramo não está atualmente com check-out?
Joe Phillips
@JoePhilllips Algumas pessoas tem como principal ramo não mestra mas em vez disso developou deve, nesse caso, o comando falhará com fatal: malformed object nameele é melhor ter um comando genérico e você tem a responsabilidade de executá-lo
smohamed
1
@JoePhilllips o objetivo desta resposta é empacotar a resposta de Adam (a principal resposta para essa pergunta) em um útil alias do git. A resposta de Adam não tem o que você está sugerindo e muitas pessoas acharam isso útil, então eu estaria inclinado a não mudar a minha. Eu recomendaria abrir a discussão sobre a resposta de Adam se você se sentir fortemente sobre ele
real_ate
13
Se adicionar -ra xargs, evitará erros desnecessários ( branch name required) ao executar esse alias várias vezes ou quando não houver nenhum ramo a ser excluído. Meu pseudônimo é assim:cleanup = "!git branch --merged | grep -v -P '^\\*|master|develop' | xargs -n1 -r git branch -d"
spezifanta 23/06
1
Comando atual não filtra mestre e desenvolver ramos
Andriy F.
83

Isso também funciona para excluir todas as ramificações mescladas, exceto a principal.

git branch --merged | grep -v '^* master$' | grep -v '^  master$' | xargs git branch -d
Ismael Abreu
fonte
3
Agora, ele não excluirá nenhum ramo masternele. Tente grep -v ^master$pelo meio.
wchargin
Eu também ia deixar | grep -v '^\*'para evitar deletting ramificação atual se você estiver não no mestre
svassr
5
Isso é ótimo, obrigado! Uma ressalva para quem usa isso: observe que há dois espaços grep -v '^ master$'. Se você digitar e perder um, será excluído masterse não estiver nele.
Styger
3
@ Mr.Polywhirl sua edição quebra o comando e você deve revertê-lo. Os dois espaços são necessários, pois git branchlistará cada nome de filial em uma nova linha com dois espaços à esquerda, se não for a filial com check-out no momento. Você basicamente garantiu que qualquer pessoa que execute esse comando excluirá sua ramificação principal, a menos que seja a ramificação com check-out atualmente.
Styger
79

Você deseja excluir os master& developbranches desses comandos.

Git local claro:

git branch --merged | grep -v '\*\|master\|develop' | xargs -n 1 git branch -d

Remoto git clear:

git branch -r --merged | grep -v '\*\|master\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin

Sincronize o registro local de filiais remotas:

git fetch -p
Guido Bouman
fonte
3
+1 para a versão remota também (mas menos necessária, pois temos --prune remota). Também vale a pena notar que thoose não vai funcionar com os mais velhos versão git
malko
4
git config --global --add fetch.prune truepodar automaticamente ao buscar ou puxar.
T3rm1
1
Lembre-se, ameixa seca não é a mesma coisa que o controle remoto. A limpeza remota na verdade exclui as ramificações remotas que são totalmente mescladas com sua ramificação atual. A remoção limpa apenas o registro local de ramificações remotas que já foram excluídas.
Guido Bouman
A palavra é totalmente um pouco enganadora, pois uma ramificação será considerada mesclada, quando foi mesclada antes, mas possui novas confirmações após a mesclagem, que não foram mescladas.
scones
Para excluir todos os controles remotos origem em uma chamada, eu usei isso:git branch -r --merged | grep -v '\*\|master\|develop' | grep '^\s*origin/' | sed 's/origin\///' | tr "\n" " " | xargs git push --delete origin
GPHemsley
48

Para aqueles que estão no Windows e preferem scripts do PowerShell, aqui está um que exclui ramificações locais mescladas:

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}
Klas Mellbourn
fonte
13
Por curiosidade, isso pode ser reduzido para git branch --merged | ?{-not ($_ -like "*master")} | %{git branch -d $_.trim()}
Iain Ballard
5
@IainBallard Claro, eu poderia ter usado aliases. Isso não é recomendado quando você deseja maximizar a legibilidade. github.com/darkoperator/PSStyleGuide/blob/master/English.md
Klas Mellbourn
1
certo. Achei sua resposta muito útil :-) Entretanto, às vezes, a sintaxe do PowerShell de forma longa atrapalha o que está acontecendo nos blocos. Mas, principalmente, eu estava propondo algo que você pode copiar / colar ou digitar como único. Obrigado novamente.
Iain Ballard
4
Aqui está um shell cmd de uma linha para o Windows que preserva o mestre e sua ramificação atual: for /f "usebackq" %B in (``git branch --merged^|findstr /v /c:"* " /c:"master"``) do @git branch -d %B(suspiro, substitua aspas duplas por simples, não sei como formatar um literal que contém aspas)
yoyo
42

Eu tenho usado a resposta de Adam há anos. Dito isto, há alguns casos em que não estava se comportando como eu esperava:

  1. ramificações que continham a palavra "mestre" foram ignoradas, por exemplo, "notmaster" ou "masterful", em vez de apenas a ramificação mestre
  2. ramificações que continham a palavra "dev" foram ignoradas, por exemplo, "dev-test", em vez de apenas a ramificação dev
  3. exclusão de ramificações acessíveis do HEAD da ramificação atual (ou seja, não necessariamente mestre)
  4. no estado HEAD desanexado, excluindo todos os ramos alcançáveis ​​da confirmação atual

1 e 2 foram diretos, com apenas uma alteração no regex. 3 depende do contexto do que você deseja (ou seja, exclua apenas os ramos que não foram mesclados no mestre ou no ramo atual). 4 tem o potencial de ser desastroso (embora recuperável com git reflog), se você o executou acidentalmente no estado HEAD desanexado.

Finalmente, eu queria que tudo isso estivesse em uma linha única que não exigisse um script separado (Bash | Ruby | Python).

TL; DR

Crie um alias do git "sweep" que aceite um -fsinalizador opcional :

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'

e invoque-o com:

git sweep

ou:

git sweep -f

A resposta longa e detalhada

Para mim, foi mais fácil criar um exemplo de repositório git com algumas ramificações e se comprometer a testar o comportamento correto:

Crie um novo repositório git com um único commit

mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"

Crie algumas novas ramificações

git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list
  bar
  develop
  foo
* master
  masterful
  notmaster

Comportamento desejado: selecione todas as ramificações mescladas, exceto: mestre, desenvolvimento ou atual

O regex original perde os ramos "masterful" e "notmaster":

git checkout foo
git branch --merged | egrep -v "(^\*|master|dev)"
  bar

Com o regex atualizado (que agora exclui "develop" em vez de "dev"):

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster

Alterne para o ramo foo, faça um novo commit e faça o checkout de um novo ramo, foobar, com base no foo:

echo "foo" > foo
git add . && git commit -am "foo"
git checkout -b foobar
echo "foobar" > foobar
git add . && git commit -am "foobar"

Minha ramificação atual é foobar, e se eu executar novamente o comando acima para listar as ramificações que desejo excluir, a ramificação "foo" será incluída mesmo que não tenha sido mesclada no master:

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  masterful
  notmaster

No entanto, se eu executar o mesmo comando no mestre, o ramo "foo" não será incluído:

git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

E isso é simplesmente porque o git branch --mergedpadrão é o HEAD do ramo atual, se não especificado de outra forma. Pelo menos para o meu fluxo de trabalho, não desejo excluir ramificações locais, a menos que tenham sido mescladas para mestre, por isso prefiro a seguinte variante:

git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Estado HEAD desanexado

Confiar no comportamento padrão de git branch --mergedtem consequências ainda mais significativas no estado HEAD desanexado:

git checkout foobar
git checkout HEAD~0
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  foobar
  masterful
  notmaster

Isso teria excluído o ramo em que eu estava, "foobar" junto com "foo", que quase certamente não é o resultado desejado. Com nosso comando revisado, no entanto:

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Uma linha, incluindo a exclusão real

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d

Tudo embrulhado em um apelido git "varredura":

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'

O alias aceita um -fsinalizador opcional . O comportamento padrão é excluir apenas as ramificações que foram mescladas no mestre, mas o -fsinalizador excluirá as ramificações que foram mescladas na ramificação atual.

git sweep
Deleted branch bar (was 9a56952).
Deleted branch masterful (was 9a56952).
Deleted branch notmaster (was 9a56952).
git sweep -f
Deleted branch foo (was 2cea1ab).
redemoinhos
fonte
Por que você precisa criar uma função? Não é git configatômico?
VasiliNovikov 8/06/19
Para lidar com o argumento opcional '-f' (se eu entendi sua pergunta corretamente) #
9292
1
mas como isso ajuda? Quero dizer o começo da expressão !f(){ git branch .... É uma declaração de função, certo? Por que não começar diretamente git branch ...?
VasiliNovikov
1
Você está absolutamente correto. Editou minha resposta de acordo. Obrigado pelo ponteiro!
Eddies
O seguinte não faria o mesmo que o modo não forçado? git checkout master && git branch -d `git branch --merged` && git checkout - Exceto que isso excluiria develop, mas pode ser uma abordagem mais simples.
Guido Bouman
18

Usando o Git versão 2.5.0:

git branch -d `git branch --merged`
drautb
fonte
16
Isso pode excluir o masterramo btw!
Wazery 7/10
4
Verdade. Só o uso quando tenho certeza de que estou ligado master.
drautb
11
git branch -d $(git branch --merged | grep -v master)
22818 alexg
1
Isso é perigoso se você tiver um fluxo, imagine que você tem um mestre <- estágio <- dev. Solução ainda mais fácil imo
Joseph Briggs
14

Você pode adicionar o commit à opção --merged. Desta forma, você pode ter certeza de remover apenas as ramificações que são mescladas, como a origem / mestre

O comando a seguir removerá as ramificações mescladas de sua origem.

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 git push origin --delete 

Você pode testar quais ramificações serão removidas substituindo a origem do git push --delete by echo

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
Jörn Reimerdes
fonte
2
Eu gosto da opção de teste
iwein 22/09/15
12

Eu uso o seguinte script Ruby para excluir minhas ramificações locais e remotas já mescladas. Se eu estiver fazendo isso para um repositório com vários controles remotos e quiser excluir apenas um, basta adicionar uma instrução select à lista de controles remotos para obter apenas os controles remotos desejados.

#!/usr/bin/env ruby

current_branch = `git symbolic-ref --short HEAD`.chomp
if current_branch != "master"
  if $?.exitstatus == 0
    puts "WARNING: You are on branch #{current_branch}, NOT master."
  else
    puts "WARNING: You are not on a branch"
  end
  puts
end

puts "Fetching merged branches..."
remote_branches= `git branch -r --merged`.
  split("\n").
  map(&:strip).
  reject {|b| b =~ /\/(#{current_branch}|master)/}

local_branches= `git branch --merged`.
  gsub(/^\* /, '').
  split("\n").
  map(&:strip).
  reject {|b| b =~ /(#{current_branch}|master)/}

if remote_branches.empty? && local_branches.empty?
  puts "No existing branches have been merged into #{current_branch}."
else
  puts "This will remove the following branches:"
  puts remote_branches.join("\n")
  puts local_branches.join("\n")
  puts "Proceed?"
  if gets =~ /^y/i
    remote_branches.each do |b|
      remote, branch = b.split(/\//)
      `git push #{remote} :#{branch}`
    end

    # Remove local branches
    `git branch -d #{local_branches.join(' ')}`
  else
    puts "No branches removed."
  end
end
mmrobins
fonte
Se importa se eu roubar esse boato para uma pequena biblioteca auxiliar de git? github.com/yupiq/git-branch-util
logan
1
Vá em frente, eu não teria colocá-lo aqui, se eu me preocupava com as pessoas que reutilizam o código de alguma forma
mmrobins
@mmrobins Você tem um extra \/no início da declaração de rejeição para a remote_brancheslinha. Isso é um erro de digitação ou serve a um propósito?
Jawwad
@mmrobins, oh nunca mente vejo a b.split(/\//)linha agora
Jawwad
Se você quiser fazer basicamente isso, mas via festa de baunilha em vez de rubi: stackoverflow.com/a/37999948/430128
Raman
11

Como excluir ramificações mescladas no console do PowerShell

git branch --merged | %{git branch -d $_.Trim()}

Se você deseja excluir nomes principais ou outros ramos, pode canalizar com o PowerShell Select-String como este e passar o resultado para git branch -d:

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})
Konstantin Tarkus
fonte
1
Respostas mais altas sugerem a filtragem de mestre ou outros ramos. Para aqueles que procuram fazer isso no PowerShell: git branch --merged | findstr / v "mestre" | % {git branch -d $ _. trim ()}
tredzko
@tredzko Bom argumento. FTR, a resposta mais alta é stackoverflow.com/questions/6127328/… - você pode repassar seu comentário com esse
link e
ele também tenta deletar * master:) #
221
9

A resposta de kuboon perdeu a exclusão de ramificações que possuem a palavra mestre no nome da ramificação. O seguinte melhora sua resposta:

git branch -r --merged | grep -v "origin/master$" | sed 's/\s*origin\///' | xargs -n 1 git push --delete origin

Obviamente, ele não exclui o ramo "mestre" em si :)

Paras
fonte
8

Não há nenhum comando no Git que faça isso automaticamente por você. Mas você pode escrever um script que use os comandos Git para fornecer o que você precisa. Isso pode ser feito de várias maneiras, dependendo do modelo de ramificação que você está usando.

Se você precisar saber se um ramo foi mesclado no mestre, o comando a seguir não produzirá saída se o myTopicBranch foi mesclado (ou seja, você pode excluí-lo)

$ git rev-list master | grep $(git rev-parse myTopicBranch)

Você pode usar o comando Git branch e analisar todos os branches no Bash e fazer um forloop sobre todos os branches. Nesse loop, você verifica com o comando acima se pode excluir o ramo ou não.

ralphtheninja
fonte
7

git branch --merged | grep -Ev '^(. master|\*)' | xargs -n 1 git branch -dexcluirá todas as filiais locais, exceto a filial com check-out atual e / ou master.

Aqui está um artigo útil para quem procura entender esses comandos: Git Clean: Excluir ramos já mesclados, de Steven Harman .

styger
fonte
7

Nota : Não estou satisfeito com as respostas anteriores (não estou trabalhando em todos os sistemas, não estou trabalhando no controle remoto, não especificando a ramificação --merged, não filtrando exatamente). Então, adiciono minha própria resposta.

Existem dois casos principais:

Local

Você deseja excluir as ramificações locais que já foram mescladas com outra ramificação local . Durante a exclusão, você deseja manter alguns ramos importantes, como mestre, desenvolvimento etc.

git branch --format "%(refname:short)" --merged master | grep -E -v '^master$|^feature/develop$' | xargs -n 1 git branch -d

Notas :

  • git branch output --format ".." é remover os espaços em branco e permitir a correspondência exata de grep
  • grep -Eé usado em vez de egrep , portanto, também funciona em sistemas sem egrep (ou seja: git para windows).
  • grep -E -v '^master$|^feature/develop$' é especificar ramificações locais que não quero excluir
  • xargs -n 1 git branch -d: executa a exclusão de ramificações locais (não funcionará em ramificações remotas)
  • é claro que você receberá um erro se tentar excluir o ramo com check-out atualmente. Então, sugiro mudar para o master de antemão.

Controlo remoto

Você deseja excluir ramificações remotas que já foram mescladas com outra ramificação remota . Durante a exclusão, você deseja manter algumas ramificações importantes, como HEAD, master, releases, etc.

git branch -r --format "%(refname:short)" --merged origin/master | grep -E -v '^*HEAD$|^*/master$|^*release' | cut -d/ -f2- | xargs -n 1 git push --delete origin

Notas :

  • para remoto, usamos a -ropção e fornecemos o nome completo da filial :origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' é combinar as ramificações remotas que não queremos excluir.
  • cut -d/ -f2-: remova o prefixo 'origin /' desnecessário que, caso contrário, é impresso pelo git branchcomando.
  • xargs -n 1 git push --delete origin : executa a exclusão de ramificações remotas.
psuzzi
fonte
7

Se você estiver no Windows, poderá usar o Windows Powershell ou o Powershell 7 com Out-GridView para ter uma boa lista de ramificações e selecionar com o mouse qual você deseja excluir:

git branch --format "%(refname:short)" --merged  | Out-GridView -PassThru | % { git branch -d $_ }

insira a descrição da imagem aqui depois de clicar em OK, o PowerShell passará os nomes desses ramos para git branch -dcomandá-los e excluí-los insira a descrição da imagem aqui

Mariusz Pawelski
fonte
6

Você pode usar a git-del-br ferramenta .

git-del-br -a

Você pode instalá-lo pipusando

pip install git-del-br

PS: Eu sou o autor da ferramenta. Quaisquer sugestões / comentários são bem-vindos.

tusharmakkar08
fonte
1
@ stackoverflow.com/users/100297/martijn-pieters : Por que essa resposta foi excluída e com voto negativo?
tusharmakkar08
1
Sua resposta e ferramenta não funcionam. Passo algumas horas nisso. Nada.
SpoiledTechie.com
@ SpoiledTechie.com: Você pode me dizer exatamente qual é o problema? Estou usando-o regularmente.
tusharmakkar08
Posso compartilhar uma captura de tela se você quiser colocar isso offline? spoiledtechie nessa coisa do google mail. :)
SpoiledTechie.com
5

Se você deseja excluir todos os ramos locais que já estão mesclados no ramo em que está atualmente, criei um comando seguro para fazer isso, com base nas respostas anteriores:

git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d

Este comando não afetará sua ramificação atual ou sua ramificação mestre. Ele também informará o que está fazendo antes, usando o sinalizador -t do xargs.

chrismendis
fonte
5

Versão em alias da resposta atualizada de Adam :

[alias]
    branch-cleanup = "!git branch --merged | egrep -v \"(^\\*|master|dev)\" | xargs git branch -d #"

Além disso, consulte esta resposta para obter dicas úteis sobre como escapar de aliases complexos.

Eliot
fonte
5

Eu uso um esquema de nomeação de esquemas git-flow, então isso funciona com muita segurança para mim:

git branch --merged | grep -e "^\s\+\(fix\|feature\)/" | xargs git branch -d

Ele basicamente procura confirmações mescladas que começam com string fix/ou feature/.

Chad M
fonte
4

Tente o seguinte comando:

git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Ao usar git rev-parse, obterá o nome do ramo atual para excluí-lo. Se você encontrou o erro, isso significa que não há ramificações locais para remover.

Para fazer o mesmo com ramificações remotas (mude origincom seu nome remoto), tente:

git push origin -vd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD) | cut -d/ -f2)

Caso você tenha vários controles remotos, adicione grep origin |antes cutpara filtrar apenas o origin.

Se o comando acima falhar, tente excluir primeiro as ramificações de rastreamento remoto mescladas:

git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Em seguida, git fetchcontrole remoto novamente e use o git push -vdcomando anterior novamente.

Se você o estiver usando com frequência, considere adicionar como alias ao seu ~/.gitconfigarquivo.

Caso você tenha removido algumas ramificações por engano, use git reflogpara encontrar as confirmações perdidas.

kenorb
fonte
4

Com base em algumas dessas respostas, eu criei meu próprio script Bash para fazer isso também !

Ele usa git branch --mergede git branch -dexclui as ramificações que foram mescladas e solicita a você cada uma das ramificações antes de excluir.

merged_branches(){
  local current_branch=$(git rev-parse --abbrev-ref HEAD)
  for branch in $(git branch --merged | cut -c3-)
    do
      echo "Branch $branch is already merged into $current_branch."
      echo "Would you like to delete it? [Y]es/[N]o "
      read REPLY
      if [[ $REPLY =~ ^[Yy] ]]; then
        git branch -d $branch
      fi
  done
}
Earlrails
fonte
4

A consulta abaixo funciona para mim

for branch in  `git branch -r --merged | grep -v '\*\|master\|develop'|awk 'NR > 0 {print$1}'|awk '{gsub(/origin\//, "")}1'`;do git push origin --delete $branch; done

e isso filtrará qualquer ramificação no tubo grep.

Funciona bem no clone http, mas não tão bem na conexão ssh.

user1460965
fonte
4

A partir de 2018.07

Adicione isso à sua [alias]seção ~/.gitconfig:

sweep = !"f() { git branch --merged | egrep -v \"(^\\*|master|dev)\" || true | xargs git branch -d; }; f"

Agora você pode simplesmente ligar git sweeppara executar a limpeza necessária.

sorin
fonte
Para mim, chamando varredura git lista apenas os ramos que devem ser limpos, mas não removê-los
Victor Moraes
4

No Windows com o git bash instalado, o egrep -v não funcionará

git branch --merged | grep -E -v "(master|test|dev)" | xargs git branch -d

onde grep -E -vé equivalente aegrep -v

Use -dpara remover ramificações já mescladas ou -Dpara remover ramificações não imersas

DevWL
fonte
O egrep -v funciona para mim. Estou usando gitbash dos gitextensions instalador embora
Joe Phillips
4

Eu tenho usado o seguinte método para remover ramificações locais e remotas mescladas em um cmd.

Eu tenho o seguinte no meu bashrcarquivo:

function rmb {
  current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
  if [ "$current_branch" != "master" ]; then
    echo "WARNING: You are on branch $current_branch, NOT master."
  fi
  echo "Fetching merged branches..."
  git remote prune origin
  remote_branches=$(git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$")
  local_branches=$(git branch --merged | grep -v 'master$' | grep -v "$current_branch$")
  if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; then
    echo "No existing branches have been merged into $current_branch."
  else
    echo "This will remove the following branches:"
    if [ -n "$remote_branches" ]; then
      echo "$remote_branches"
    fi
    if [ -n "$local_branches" ]; then
      echo "$local_branches"
    fi
    read -p "Continue? (y/n): " -n 1 choice
    echo
    if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
      # Remove remote branches
      git push origin `git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$" | sed 's/origin\//:/g' | tr -d '\n'`
      # Remove local branches
      git branch -d `git branch --merged | grep -v 'master$' | grep -v "$current_branch$" | sed 's/origin\///g' | tr -d '\n'`
    else
      echo "No branches removed."
    fi
  fi
}

fonte original

Isso não exclui a ramificação principal, mas remove ramificações locais E remotas mescladas . Depois de ter isso em seu arquivo rc, basta executar rmb, você verá uma lista de ramos mesclados que serão limpos e solicitados para confirmação da ação. Você pode modificar o código para não pedir confirmação também, mas provavelmente é bom mantê-lo.

Prashant
fonte
3

Escreva um script no qual o Git verifique todas as ramificações que foram mescladas no mestre.

Então faça git checkout master.

Por fim, exclua as ramificações mescladas.

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git checkout $branchnew
done

git checkout master

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git push origin --delete $branchnew
done
Komu
fonte
3

A solução aceita é muito boa, mas o problema é que ela também exclui ramificações locais que ainda não foram mescladas em um controle remoto.

Se você olhar para a saída, verá algo como

$ git branch --merged master -v
  api_doc                  3a05427 [gone] Start of describing the Java API
  bla                      52e080a Update wording.
  branch-1.0               32f1a72 [maven-release-plugin] prepare release 1.0.1
  initial_proposal         6e59fb0 [gone] Original proposal, converted to AsciiDoc.
  issue_248                be2ba3c Skip unit-for-type checking. This needs more work. (#254)
  master                   be2ba3c Skip unit-for-type checking. This needs more work. (#254)

Ramificações blae issue_248ramificações locais que seriam excluídas silenciosamente.

Mas você também pode ver a palavra [gone], que indica ramificações que foram enviadas para um controle remoto (que agora se foi) e, portanto, indica que ramificações podem ser excluídas.

A resposta original pode, portanto, ser alterada para (dividida em várias linhas para menor comprimento de linha)

git branch --merged master -v | \
     grep  "\\[gone\\]" | \
     sed -e 's/^..//' -e 's/\S* .*//' | \
      xargs git branch -d

para proteger os ramos ainda não mesclados. Também não é necessário o grepping para o mestre protegê-lo, pois ele tem um controle remoto na origem e não aparece como desaparecido.

Heiko Rupp
fonte
3

Para mim git branch --merged, não mostra ramificações que foram mescladas via GitHub PR. Não tenho certeza dos motivos, mas uso a seguinte linha para excluir todas as ramificações locais que não possuem ramificação de rastreamento remoto :

diff <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | grep '<' | cut -c 3- | xargs git branch -D

Explicação:

  • git branch --format "%(refname:short)" fornece uma lista de filiais locais
  • git branch -r | grep -v HEAD | cut -d/ -f2- fornece uma lista de ramificações remotas, filtrando HEAD
  • diff <(...) <(...) fornece uma diferença de saída de dois comandos entre parênteses
  • grep '<' filtra ramificações existentes na primeira lista, mas não na segunda
  • cut -c 3- fornece uma linha a partir do terceiro caractere, removendo assim o prefixo <
  • xargs git branch -Dexecuta git branch -Dcontra cada nome de filial

Como alternativa, você pode evitar grep -v '<'assim:

diff --old-line-format="%L" --new-line-format="" --unchanged-line-format="" <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | xargs git branch -D
folex
fonte