¿Cómo puedo eliminar todas las ramas de Git que se han fusionado?

1936

Tengo muchas ramas Git. ¿Cómo elimino ramas que ya se han fusionado? ¿Hay alguna manera fácil de eliminarlos todos en lugar de eliminarlos uno por uno?

Nyambaa
fuente
46
Para ser un poco más específico, se git branch -Delimina cualquier rama, ya sea que se haya fusionado o no.
PhilT
12
También puede hacerlo directamente desde GitHub, si va a la sección 'ramas' de su repositorio (por ejemplo, github.com/<username>/<repo_name>/branches ). Debe haber una lista de todas sus ramas, con un icono rojo de papelera en el lado que eliminará la rama seleccionada. ¡Mucho más rápido que hacerlo en la terminal! También mostrará qué tan adelante / atrás está mastercada rama. Sin embargo, su cliente local seguirá enumerando las ramas antiguas si ejecuta git branch -a; use git fetch --prunepara eliminarlos (según esta respuesta ).
user5359531
3
Script para hacer esto local o remotamente, con controles de seguridad y "ramas seguras" preconfiguradas : github.com/fatso83/dotfiles/tree/master/utils/…git delete-merged --doit origin ogit delete-merged --doit --local
oligofren
También podría usar esta aplicación para eliminar automáticamente las ramas fusionadas.
Sebass van Boxel
rm -fr work && git clone http://example.com/work.gitCon los años se ha convertido en la forma más fácil de salir de un aprieto con git.
Reactgular

Respuestas:

3117

ACTUALIZAR:

Puede agregar otras ramas para excluirlas como master y dev si su flujo de trabajo las tiene como un posible antepasado. Por lo general, me ramifico de una etiqueta "sprint-start" y master, dev y qa no son ancestros.

Primero, enumere todas las ramas que se fusionaron en remoto.

git branch --merged

Es posible que vea algunas ramas que no desea eliminar. Podemos agregar algunos argumentos para omitir ramas importantes que no queremos eliminar como master o desarrollo. El siguiente comando omitirá la rama maestra y todo lo que tenga dev.

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

Si desea omitir, puede agregarlo al comando egrep de la siguiente manera. La rama skip_branch_nameno se eliminará.

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

Para eliminar todas las sucursales locales que ya están fusionadas en la sucursal actualmente desprotegida:

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

Puede ver que master y dev están excluidos en caso de que sean ancestros.


Puede eliminar una sucursal local fusionada con:

git branch -d branchname

Si no está fusionado, use:

git branch -D branchname

Para eliminarlo del uso remoto:

git push --delete origin branchname

git push origin :branchname    # for really old git

Una vez que elimine la rama del control remoto, puede podar para deshacerse de las ramas de seguimiento remoto con:

git remote prune origin

o pode ramas de seguimiento remoto individuales, como sugiere la otra respuesta, con:

git branch -dr branchname

Espero que esto ayude.

Adam Dymitruk
fuente
46
ADVERTENCIA: si acaba de crear una rama, también eliminará esa. Asegúrese de no tener una rama recién creada en la lista antes de ejecutar el comando superior.
Gary Haran
154
OPUESTO DE ADVERTENCIA: reflog guardará su tocino. Entonces no te preocupes.
Adam Dymitruk
33
Tenga en cuenta que el primer comando solo elimina ramas locales, por lo que no es tan "peligroso" como algunos han señalado.
ifightcrime
79
Variante de PowerShell, para poder encontrarla aquí la próxima vez que busqué en Google la respuesta:git branch --merged | %{$_.trim()} | ?{$_ -notmatch 'develop' -and $_ -notmatch 'master'} | %{git branch -d $_}
vorou
23
Esto produce un error fatal: branch name requiredsi no tiene ramas que deberían eliminarse. Para evitar eso, puede pasar -rpara xargsque no se ejecute git branch -dsi el stdin está vacío. (Esta es una extensión GNU xargs, de acuerdo con la página del manual).
Marius Gedminas
457

Para eliminar todas las ramas en el control remoto que ya están fusionadas:

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

En versiones más recientes de Git

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

ACTUALIZACIÓN (por @oliver; ya que no cabe en el comentario, pero ya hay suficientes respuestas) : si está en la rama ABC, entonces ABC aparecerá en los resultados degit branch -r --merged porque la rama no está especificada, por lo que la rama se predetermina a la rama actual, y una rama siempre califica como fusionado consigo mismo (¡porque no hay diferencias entre una rama y sí mismo!).

Entonces, especifique la rama:

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

O primer checkout master:

git checkout master | git branch -r --merged | grep -v ...
kuboon
fuente
18
La mejor respuesta con diferencia. Solo una nota, mi rama maestra se llama devasí que tuve que cambiar eso
Dorian
41
Tuve que agregar | grep origindespués grep -v masterpara evitar empujar ramas de otros controles remotos al origen. Recomiendo encarecidamente probar la salida de antemano, usandogit branch -r --merged | grep -v master | grep origin | sed 's/origin\//:/' | xargs -n 1 echo
L0LN1NJ4
99
Modifiqué un poco para excluir la developrama también. git branch -r --merged | grep -v master | grep -v develop | sed 's/origin\///' | xargs -n 1 git push --delete origin. Ahora esto resultó ser mi alias.
sarat
8
Lo que hizo que esta sea la mejor respuesta que he leído, es el -rargumento, que no he visto mencionado en ningún otro lado. Se da por sentado que solo vale la pena realizar algunas tareas de limpieza en las sucursales locales. Pero los controles remotos también están llenos de basura.
Asbjørn Ulsberg
19
Precaución: solo se dio cuenta: esto obviamente encontrará ramas fusionadas con la rama actual , no maestra, por lo que si está en myFeatureBranchella se borrará origin/myFeatureBranch. Probablemente es mejor git checkout masterprimero.
jakub.g
190

Solo extendiendo un poco la respuesta de Adam:

Agregue esto a su configuración de Git ejecutando git config -e --global

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

Y luego puede eliminar todas las ramas locales fusionadas haciendo un simple git cleanup.

real_ate
fuente
11
¿No debería ser el primer comando: git branch --merged masterya que desea ver lo que se ha fusionado en la rama maestra, no actualmente desprotegida?
Joe Phillips
@JoePhilllips Algunas personas tiene la rama principal no maestro, pero en lugar developo devcomo en este caso, el comando fallará con fatal: malformed object nameque es mejor tener un dominio genérico y tiene la responsabilidad de ejecutarlo
smohamed
1
@JoePhilllips el punto de esta respuesta es empaquetar la respuesta de Adam (la respuesta principal para esta pregunta) en un útil alias git. La respuesta de Adam no tiene lo que estás sugiriendo y mucha gente lo ha encontrado útil, por lo que me inclinaría a no cambiar la mía. Recomendaría abrir la discusión sobre la respuesta de Adam si se siente fuertemente al respecto
real_ate
13
Agregar -ra xargsevitará errores innecesarios ( branch name required) al ejecutar este alias varias veces o cuando no quede ninguna rama para eliminar. Mi alias se ve así:cleanup = "!git branch --merged | grep -v -P '^\\*|master|develop' | xargs -n1 -r git branch -d"
spezifanta
1
El comando actual no filtra el master y desarrolla ramas
Andriy F.
83

Esto también funciona para eliminar todas las ramas fusionadas excepto la maestra.

git branch --merged | grep -v '^* master$' | grep -v '^  master$' | xargs git branch -d
Ismael Abreu
fuente
3
Ahora no eliminará ninguna rama que mastercontenga. Intenta grep -v ^master$por el medio.
wchargin
También dejaría | grep -v '^\*'de evitar eliminar la rama actual si no estás en master
svassr
55
Esto es genial, gracias! Una advertencia para cualquiera que use esto: tenga en cuenta que hay dos espacios en grep -v '^ master$'. Si lo escribe usted mismo y se pierde uno, lo eliminará mastersi no está en él.
styger
3
@ Mr.Polywhirl, su edición rompe el comando y debe revertirlo. Los dos espacios son necesarios, ya git branchque enumerará cada nombre de rama en una nueva línea con dos espacios a la izquierda si no es la rama actualmente desprotegida. Básicamente, ha garantizado que cualquiera que ejecute este comando eliminará su rama maestra a menos que sea la rama actualmente desprotegida.
styger
79

Deberá excluir las ramas master& developde esos comandos.

Git local claro:

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

Git remoto claro:

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

Sincronizar registro local de sucursales remotas:

git fetch -p
Guido Bouman
fuente
3
+1 para la versión remota también (pero menos necesaria ya que tenemos remoto --prune). También vale la pena señalar que esos no funcionarán con la versión anterior de git
malko
44
git config --global --add fetch.prune truepara podar automáticamente al buscar o tirar.
T3rm1
1
Eso sí, la ciruela pasa no es lo mismo que el control remoto. El borrado remoto en realidad elimina las ramas remotas que están completamente fusionadas con su rama actual. Prune solo limpia su registro local de ramas remotas que ya están eliminadas.
Guido Bouman el
La palabra completamente es un poco engañosa, ya que una rama se considerará fusionada cuando se fusionó antes, pero tiene nuevas confirmaciones después de la fusión, que no se fusionaron.
bollos
Para eliminar todos los controles remotos de origen en una sola llamada, utilicé esto:git branch -r --merged | grep -v '\*\|master\|develop' | grep '^\s*origin/' | sed 's/origin\///' | tr "\n" " " | xargs git push --delete origin
GPHemsley
48

Para aquellos de ustedes que están en Windows y prefieren los scripts de PowerShell, aquí hay uno que elimina las ramas locales fusionadas:

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}
Klas Mellbourn
fuente
13
Por curiosidad, esto se puede acortar a git branch --merged | ?{-not ($_ -like "*master")} | %{git branch -d $_.trim()}
Iain Ballard
55
@IainBallard Claro, podría haber usado alias. Eso no se recomienda cuando desea maximizar la legibilidad. github.com/darkoperator/PSStyleGuide/blob/master/English.md
Klas Mellbourn
1
Por supuesto. Su respuesta me pareció muy útil :-) Sin embargo, a veces la sintaxis de PowerShell de larga duración se interpone en el camino de lo que está sucediendo en los bloques. Pero principalmente, estaba presentando algo que podría copiar / pegar o escribir como una sola vez. Gracias de nuevo.
Iain Ballard
44
Aquí hay una línea para el shell de cmd de Windows que conserva el maestro y su rama actual: for /f "usebackq" %B in (``git branch --merged^|findstr /v /c:"* " /c:"master"``) do @git branch -d %B(suspiro, reemplace las comillas dobles por simples, no estoy seguro de cómo formatear un literal que contenga comillas inversas)
yoyo
42

He usado la respuesta de Adam por años. Dicho esto, hay algunos casos en los que no se comportó como esperaba:

  1. se ignoraron las ramas que contenían la palabra "maestro", por ejemplo, "no maestro" o "maestro", en lugar de solo la rama maestra
  2. las ramas que contenían la palabra "dev" fueron ignoradas, por ejemplo, "dev-test", en lugar de solo la rama dev
  3. eliminar ramas a las que se puede acceder desde el HEAD de la rama actual (es decir, no necesariamente maestro)
  4. en estado HEAD separado, eliminando cada rama accesible desde el commit actual

1 y 2 fueron fáciles de abordar, con solo un cambio en la expresión regular. 3 depende del contexto de lo que desee (es decir, solo elimine las ramas que no se han fusionado en el maestro o en su rama actual). 4 tiene el potencial de ser desastroso (aunque recuperable con git reflog), si accidentalmente ejecutó esto en estado HEAD separado.

Finalmente, quería que todo esto estuviera en una línea que no requiriera un script separado (Bash | Ruby | Python).

TL; DR

Cree un "barrido" de alias de git que acepte una marca opcional -f:

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

e invocarlo con:

git sweep

o:

git sweep -f

La respuesta larga y detallada

Fue más fácil para mí crear un ejemplo de repositorio de git con algunas ramas y se compromete a probar el comportamiento correcto:

Crea un nuevo repositorio de git con un solo commit

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

Crea algunas ramas nuevas

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

Comportamiento deseado: seleccione todas las ramas fusionadas excepto: maestro, desarrollo o actual

La expresión regular original pierde las ramas "maestra" y "no maestra":

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

Con la expresión regular actualizada (que ahora excluye "desarrollar" en lugar de "dev"):

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

Cambie a la sucursal foo, realice una nueva confirmación, luego revise una nueva rama, foobar, basada en foo:

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

Mi rama actual es foobar, y si vuelvo a ejecutar el comando anterior para enumerar las ramas que quiero eliminar, la rama "foo" se incluye aunque no se haya fusionado en master:

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

Sin embargo, si ejecuto el mismo comando en master, la rama "foo" no está incluida:

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

Y esto se debe simplemente a que el valor git branch --mergedpredeterminado es HEAD de la rama actual si no se especifica lo contrario. Al menos para mi flujo de trabajo, no quiero eliminar sucursales locales a menos que se hayan fusionado con master, por lo que prefiero la siguiente variante:

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

Estado HEAD separado

Confiar en el comportamiento predeterminado de git branch --mergedtiene consecuencias aún más significativas en el estado HEAD separado:

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

Esto habría eliminado la rama en la que estaba, "foobar" junto con "foo", lo que casi seguro no es el resultado deseado. Con nuestro comando revisado, sin embargo:

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

Una línea, incluida la eliminación real

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

Todo envuelto en un "barrido" de alias git:

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

El alias acepta una -fbandera opcional . El comportamiento predeterminado es eliminar solo las ramas que se han fusionado en el maestro, pero el -findicador eliminará las ramas que se han fusionado en la rama actual.

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).
remolinos
fuente
¿Por qué necesitas crear una función? ¿No es git configatómico?
VasiliNovikov
Para tratar con el argumento opcional '-f' (si entiendo su pregunta correctamente)
eddies
1
pero como ayuda? Me refiero al inicio de la expresión, !f(){ git branch .... Es una declaración de función, ¿verdad? ¿Por qué no comenzar directamente con git branch ...?
VasiliNovikov
1
Estás absolutamente en lo correcto. Edité mi respuesta en consecuencia. ¡Gracias por la anotación!
Eddies
¿Lo siguiente no haría lo mismo que el modo sin fuerza? git checkout master && git branch -d `git branch --merged` && git checkout - Excepto que eliminaría develop, pero podría ser un enfoque más simple.
Guido Bouman
18

Usando Git versión 2.5.0:

git branch -d `git branch --merged`
drautb
fuente
16
Esto puede eliminar la masterrama por cierto!
Wazery
44
Cierto. Solo lo uso cuando estoy seguro de que estoy encendido master.
drautb
11
git branch -d $(git branch --merged | grep -v master)
alexg
1
Esto es peligroso si tienes un flujo, imagina que tienes master <- stage <- dev. Sigue siendo la solución más fácil
Joseph Briggs
14

Puede agregar el commit a la opción - fusionada. De esta manera, puede asegurarse de eliminar solo las ramas que están fusionadas, es decir, el origen / maestro

El siguiente comando eliminará las ramas fusionadas de su origen.

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

Puede probar qué ramas se eliminarán reemplazando el origen de git push: eliminar con eco

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
Jörn Reimerdes
fuente
2
Me gusta la opción de prueba
iwein
12

Utilizo el siguiente script de Ruby para eliminar mis ramas locales y remotas ya fusionadas. Si lo estoy haciendo para un repositorio con múltiples controles remotos y solo quiero eliminar de uno, solo agrego una instrucción select a la lista de controles remotos para obtener solo los controles remotos que quiero.

#!/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
fuente
¿Te importa si robo este dato para una pequeña biblioteca auxiliar de git? github.com/yupiq/git-branch-util
logan
1
Ir a por ello, no me he puesto aquí si me preocupaba por la gente que reutilizan el código de alguna manera
mmrobins
@mmrobins Tiene un extra \/al comienzo de la declaración de rechazo para la remote_brancheslínea. ¿Es eso un error tipográfico o sirve para un propósito?
Jawwad
@mmrobins, oh no importa, b.split(/\//)ahora veo la línea
Jawwad
Si desea hacer básicamente esto, pero a través de vanilla bash en lugar de ruby: stackoverflow.com/a/37999948/430128
Raman el
11

Cómo eliminar ramas fusionadas en la consola de PowerShell

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

Si desea excluir el nombre maestro o cualquier otro nombre de rama, puede canalizar con PowerShell Select-String de esta manera y pasar el resultado a git branch -d:

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})
Konstantin Tarkus
fuente
1
Las respuestas más altas sugieren un filtro principal u otras ramas. Para aquellos que buscan hacer eso en powershell: git branch --merged | Findstr / v "maestro" | % {git branch -d $ _. trim ()}
tredzko
@tredzko Buen punto. FTR la respuesta más alta es stackoverflow.com/questions/6127328/… - podría volver a publicar su comentario con ese
enlace
también intenta eliminar * master:)
iesen
9

La respuesta de kuboon no borró las ramas que tienen la palabra master en el nombre de la rama. Lo siguiente mejora en su respuesta:

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

Por supuesto, no elimina la rama "maestra" en sí :)

Paras
fuente
8

No hay ningún comando en Git que lo haga automáticamente. Pero puede escribir un script que use comandos Git para darle lo que necesita. Esto podría hacerse de muchas maneras dependiendo del modelo de ramificación que esté utilizando.

Si necesita saber si una rama se ha fusionado con el maestro, el siguiente comando no generará ningún resultado si myTopicBranch se ha fusionado (es decir, puede eliminarlo)

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

Puede usar el comando de rama Git y analizar todas las ramas en Bash y hacer un forbucle sobre todas las ramas. En este bucle, verifica con el comando anterior si puede eliminar la rama o no.

ralphtheninja
fuente
7

git branch --merged | grep -Ev '^(. master|\*)' | xargs -n 1 git branch -d eliminará todas las sucursales locales, excepto la sucursal desprotegida actual y / o master .

Aquí hay un artículo útil para aquellos que buscan comprender estos comandos: Git Clean: Eliminar ramas ya fusionadas, por Steven Harman .

styger
fuente
7

Nota : No estoy satisfecho con las respuestas anteriores (no funciona en todos los sistemas, no funciona en remoto, no especifica la rama combinada, no filtra exactamente). Entonces, agrego mi propia respuesta.

Hay dos casos principales:

Local

Desea eliminar sucursales locales que ya están fusionadas con otra sucursal local . Durante la eliminación, desea mantener algunas ramas importantes, como master, desarrollo, 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 ".." es eliminar espacios en blanco y permitir una coincidencia grep exacta
  • grep -Ese usa en lugar de egrep , por lo que funciona también en sistemas sin egrep (es decir, git para windows).
  • grep -E -v '^master$|^feature/develop$' es especificar sucursales locales que no quiero eliminar
  • xargs -n 1 git branch -d: realiza la eliminación de sucursales locales (no funcionará para las remotas)
  • por supuesto , obtendrá un error si intenta eliminar la sucursal actualmente desprotegida. Por lo tanto, sugiero cambiar a maestro de antemano.

Remoto

Desea eliminar ramas remotas que ya están fusionadas con otra rama remota . Durante la eliminación, desea mantener algunas ramas 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 la -ropción y proporcionamos el nombre completo de la sucursal :origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' es hacer coincidir las ramas remotas que no queremos eliminar.
  • cut -d/ -f2-: elimina el prefijo 'origin /' innecesario que, de lo contrario, el git branchcomando imprime .
  • xargs -n 1 git push --delete origin : realiza la eliminación de ramas remotas.
psuzzi
fuente
7

Si está en Windows, puede usar Windows Powershell o Powershell 7 con Out-GridView para tener una buena lista de ramas y seleccionar con el mouse cuál desea eliminar:

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

ingrese la descripción de la imagen aquí después de hacer clic en Aceptar, Powershell pasará los nombres de estas ramas al git branch -dcomando y los eliminará ingrese la descripción de la imagen aquí

Mariusz Pawelski
fuente
6

Puedes usar la git-del-br herramienta .

git-del-br -a

Puedes instalarlo pipusando

pip install git-del-br

PD: Soy el autor de la herramienta. Cualquier sugerencia / comentario son bienvenidos.

tusharmakkar08
fuente
1
@ stackoverflow.com/users/100297/martijn-pieters : ¿Por qué esta respuesta fue eliminada y rechazada?
tusharmakkar08
1
Tu respuesta y tu herramienta no funcionan. Me paso un par de horas en eso. Nada.
SpoiledTechie.com
@ SpoiledTechie.com: ¿Puede decirme qué problema enfrenta exactamente? Lo estoy usando regularmente.
tusharmakkar08
¿Puedo compartir una captura de pantalla si quieres desconectarlo? spoiledtechie en esa cosa del correo de google. :)
SpoiledTechie.com
5

Si desea eliminar todas las sucursales locales que ya están fusionadas en la sucursal en la que se encuentra actualmente, se me ocurrió un comando seguro para hacerlo, basado en respuestas anteriores:

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

Este comando no afectará su rama actual o su rama maestra. También le dirá qué está haciendo antes de hacerlo, utilizando el indicador -t de xargs.

chrismendis
fuente
5

Versión alias de la respuesta actualizada de Adam :

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

Además, consulte esta respuesta para obtener consejos útiles sobre cómo escapar de los alias complejos.

Eliot
fuente
5

Utilizo un esquema de nomenclatura git-flow esque, por lo que esto funciona de manera muy segura para mí:

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

Básicamente busca confirmaciones fusionadas que comienzan con una cadena fix/o feature/.

Chad M
fuente
4

Pruebe el siguiente comando:

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

Al usar git rev-parseobtendrá el nombre actual de la sucursal para excluirlo. Si recibió el error, eso significa que no hay sucursales locales para eliminar.

Para hacer lo mismo con las ramas remotas (cambie origincon su nombre remoto), intente:

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

En caso de tener múltiples controles remotos, agregue grep origin |antes cutpara filtrar solo el origin.

Si el comando anterior falla, intente eliminar primero las ramas combinadas de seguimiento remoto:

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

Luego git fetchel control remoto nuevamente y use el git push -vdcomando anterior nuevamente.

Si lo usa con frecuencia, considere agregar como alias en su ~/.gitconfigarchivo.

En caso de que haya eliminado algunas ramas por error, use git reflogpara encontrar los commits perdidos.

kenorb
fuente
4

¡Basado en algunas de estas respuestas, hice mi propio script Bash para hacerlo también !

Utiliza git branch --mergedy git branch -dpara eliminar las ramas que se han fusionado y le solicita cada una de las ramas antes de eliminar.

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
fuente
4

La consulta a continuación funciona para mí

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

y esto filtrará cualquier rama dada en la tubería grep.

Funciona bien sobre http clone, pero no tan bien para la conexión ssh.

usuario1460965
fuente
4

A partir de 2018.07

Agregue esto a la [alias]sección de su ~/.gitconfig:

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

Ahora puede llamar git sweeppara realizar la limpieza necesaria.

Sorin
fuente
Para mí, llamar a git sweep solo enumera las ramas que deben limpiarse, pero no las elimina
Victor Moraes
4

En Windows con git bash instalado egrep -v no funcionará

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

donde grep -E -ves equivalente deegrep -v

Utilizar -dpara eliminar ya fusionado ramas o -Dquitar sin combinar ramas

DevWL
fuente
egrep -v funciona para mí. Sin embargo
Joe Phillips
4

He estado usando el siguiente método para eliminar ramas locales y remotas fusionadas en un cmd.

Tengo lo siguiente en mi bashrcarchivo:

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
}

fuente original

Esto no elimina la rama maestra, pero elimina las ramas locales y remotas fusionadas . Una vez que tenga esto en su archivo rc, simplemente ejecute rmb, se le mostrará una lista de ramas fusionadas que se limpiarán y se le pedirá confirmación sobre la acción. También puede modificar el código para no solicitar confirmación, pero probablemente sea bueno mantenerlo.

Prasante
fuente
3

Escriba un script en el que Git compruebe todas las ramas que se han fusionado para dominar.

Entonces hazlo git checkout master.

Finalmente, elimine las ramas fusionadas.

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
fuente
3

La solución aceptada es bastante buena, pero tiene el problema de que también elimina las sucursales locales que aún no se fusionaron en un control remoto.

Si miras el resultado, verás 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)

Ramas blay issue_248son ramas locales que se eliminarían en silencio.

Pero también puede ver la palabra [gone], que indica ramas que habían sido empujadas a un control remoto (que ahora está desaparecido) y, por lo tanto, denotan que las ramas se pueden eliminar.

Por lo tanto, la respuesta original se puede cambiar a (dividir en varias líneas para una longitud de línea más corta)

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

para proteger las ramas aún no fusionadas. Tampoco es necesario el grepping para master para protegerlo, ya que tiene un control remoto en origen y no aparece como desaparecido.

Heiko Rupp
fuente
3

Para mí git branch --mergedno muestra ramas que se fusionaron a través de GitHub PR. No estoy seguro de los motivos, pero uso la siguiente línea para eliminar todas las ramas locales que no tienen una rama de seguimiento remoto :

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

Explicación:

  • git branch --format "%(refname:short)" da una lista de sucursales locales
  • git branch -r | grep -v HEAD | cut -d/ -f2- da una lista de ramas remotas, filtrando HEAD
  • diff <(...) <(...) da una diferencia de salida de dos comandos entre paréntesis
  • grep '<' filtra las ramas que existen en la primera lista, pero no en la segunda
  • cut -c 3- da línea a partir del 3er carácter, eliminando así el prefijo <
  • xargs git branch -Dse ejecuta git branch -Dcontra cada nombre de rama

Alternativamente, puede evitar grep -v '<'así:

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
fuente