remotas - ver ramas git
¿Cómo puedo eliminar todas las ramas de Git que se han fusionado? (30)
Tengo muchas ramas de git. ¿Cómo borro ramas que ya han sido fusionadas? ¿Hay una manera fácil de eliminarlos todos en lugar de eliminarlos uno por uno?
A partir de 2018.07
Agregue esto a la sección [alias]
de su ~/.gitconfig
:
sweep = !"f() { git branch --merged | egrep -v /"(^//*|master|dev)/" || true | xargs git branch -d; }; f"
Ahora puede llamar a git sweep
para realizar la limpieza necesaria.
Cómo eliminar ramas fusionadas en la consola de PowerShell
git branch --merged | %{git branch -d $_.Trim()}
¡Basándome en algunas de estas respuestas, hice mi propio script de Bash para hacerlo también !
Utiliza git branch --merged
y git branch -d
para eliminar las ramas que se han fusionado y le solicita cada una de las ramas antes de eliminarlas.
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
}
ACTUALIZAR:
Puede agregar otras ramas para excluirlas como master y dev si su flujo de trabajo tiene esas como posibles antepasados. Por lo general, me bifurco de una etiqueta de inicio rápido y el maestro, dev y qa no son ancestros.
Para eliminar todas las sucursales locales que ya están fusionadas en la rama actualmente retirada:
git branch --merged | egrep -v "(^/*|master|dev)" | xargs git branch -d
Puedes ver que master y dev están excluidos en caso de que sean un ancestro.
Puede eliminar una rama local combinada con:
git branch -d branchname
Si no está fusionado, use:
git branch -D branchname
Para eliminarlo del control remoto en versiones antiguas de Git use:
git push origin :branchname
En versiones más recientes de uso de Git:
git push --delete origin branchname
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 podar ramas de seguimiento remoto individuales, como sugiere la otra respuesta, con:
git branch -dr branchname
Espero que esto ayude.
Debajo de la consulta funciona para mi
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 con clones de http, pero no tan bien para la conexión ssh.
Escriba un script en el que Git verifique todas las ramas que se han fusionado para dominar.
Entonces haz 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
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
He usado la respuesta de Adam por años. Dicho esto, hay algunos casos en los que no se comportó como esperaba:
- las ramas que contenían la palabra "maestro" se ignoraron, por ejemplo, "no maestro" o "maestro", en lugar de solo la rama maestra
- las ramas que contenían la palabra "dev" se ignoraron, por ejemplo, "dev-test", en lugar de solo la rama dev
- eliminar ramas que son accesibles desde la CABEZA de la rama actual (es decir, no necesariamente maestra)
- en estado HEAD separado, eliminando cada rama accesible desde el compromiso 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 eliminar las ramas que no se hayan fusionado en el maestro o en su rama actual). 4 tiene el potencial de ser desastroso (aunque recuperable con git reflog
), si involuntariamente ejecutó esto en estado HEAD separado.
Finalmente, quería que todo estuviera en una sola línea que no requiriera un script separado (Bash | Ruby | Python).
TL; DR
Cree un "barrido" de alias de git que acepte un indicador -f
opcional:
git config --global alias.sweep ''!f(){ git branch --merged $([[ $1 != "-f" ]] /
&& git rev-parse master) | egrep -v "(^/*|^/s*(master|develop)$)" /
| xargs git branch -d; }; f''
y lo invocamos con:
git sweep
o:
git sweep -f
La respuesta larga y detallada.
Fue más fácil para mí crear un ejemplo de repositorio git con algunas ramas y se compromete a probar el comportamiento correcto:
Crea un nuevo repositorio 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: maestra, desarrollada o actual
El regex original pierde las ramas "masterful" y "notmaster":
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 rama foo, haga un nuevo compromiso y luego seleccione 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 el maestro:
git branch --merged | egrep -v "(^/*|^/s*(master|develop)$)"
bar foo masterful notmaster
Sin embargo, si ejecuto el mismo comando en el maestro, 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 git branch --merged
valores predeterminados de HEAD de la rama actual si no se especifica lo contrario. Al menos para mi flujo de trabajo, no quiero eliminar las sucursales locales a menos que se hayan fusionado para dominar, así 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 la git branch --merged
tiene consecuencias aún más significativas en el estado HEAD desconectado:
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", que casi seguramente 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, incluyendo la eliminación real
git branch --merged $(git rev-parse master) | egrep -v "(^/*|^/s*(master|develop)$)" | xargs git branch -d
Todo envuelto en un alias de git "barrido":
git config --global alias.sweep ''!f(){ git branch --merged $([[ $1 != "-f" ]] /
&& git rev-parse master) | egrep -v "(^/*|^/s*(master|develop)$)" /
| xargs git branch -d; }; f''
El alias acepta una opción -f
bandera. El comportamiento predeterminado es eliminar solo las ramas que se han fusionado en el maestro, pero la -f
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).
La respuesta de Kuboon falló en eliminar las ramas que tienen la palabra maestro en el nombre de la rama. La 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í misma :)
La solución aceptada es bastante buena, pero tiene el único problema de que también elimina las sucursales locales que aún no se fusionaron en un control remoto.
Si miras la salida de ti 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)
Las sucursales bla
y issue_248
son sucursales locales que se eliminarían de forma silenciosa.
Pero también puede ver la palabra [gone]
, que indica las ramas que se han empujado a un control remoto (que ahora se ha ido) y, por lo tanto, denotar ramas se pueden eliminar.
La respuesta original se puede cambiar a (dividir en multilínea para una 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. Además, el grepping para que el maestro lo proteja, no es necesario, ya que tiene un control remoto en el origen y no aparece como desaparecido.
No hay ningún comando en Git que lo haga automáticamente. Pero puede escribir un script que use los comandos de Git para darle lo que necesita. Esto se puede hacer de muchas maneras dependiendo del modelo de ramificación que esté utilizando.
Si necesita saber si una rama se ha fusionado en el maestro, el siguiente comando no generará resultados si myTopicBranch se ha fusionado (es decir, puede eliminarlo)
$ git rev-list master | grep $(git rev-parse myTopicBranch)
Podría usar el comando Git branch y analizar todas las ramas en Bash y hacer un bucle for
en todas las ramas. En este bucle, verifique con el comando anterior si puede eliminar la rama o no.
Para Windows, puede instalar Cygwin y eliminar todas las sucursales remotas con el siguiente comando:
git branch -r --merged | "C:/cygwin64/bin/grep.exe" -v master | "C:/cygwin64/bin/sed.exe" ''s/origin////'' | "C:/cygwin64/bin/xargs.exe" -n 1 git push --delete origin
Para aquellos de ustedes que están en Windows y prefieren los scripts de PowerShell, aquí hay uno que elimina las ramas fusionadas locales:
function Remove-MergedBranches
{
git branch --merged |
ForEach-Object { $_.Trim() } |
Where-Object {$_ -NotMatch "^/*"} |
Where-Object {-not ( $_ -Like "*master" )} |
ForEach-Object { git branch -d $_ }
}
Para eliminar las ramas locales que se han fusionado con la rama maestra, estoy usando el siguiente alias ( git config -e --global
):
cleanup = "!git branch --merged master | grep -v ''^*//|master'' | xargs -n 1 git branch -D"
Estoy usando git branch -D
para evitar el error: The branch ''some-branch'' is not fully merged.
mensajes mientras mi compra actual es diferente de la rama maestra.
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
Para evitar ejecutar accidentalmente el comando desde cualquier otra rama que no sea la maestra, uso el siguiente script de bash. De lo contrario, ejecuta git branch --merged | grep -v "/*" | xargs -n 1 git branch -d
git branch --merged | grep -v "/*" | xargs -n 1 git branch -d
git branch --merged | grep -v "/*" | xargs -n 1 git branch -d
de una rama que se ha fusionado fuera del maestro podría eliminar la rama maestra.
#!/bin/bash
branch_name="$(git symbolic-ref HEAD 2>/dev/null)" ||
branch_name="(unnamed branch)" # detached HEAD
branch_name=${branch_name##refs/heads/}
if [[ $branch_name == ''master'' ]]; then
read -r -p "Are you sure? [y/N] " response
if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then
git branch --merged | grep -v "/*" | xargs -n 1 git branch -d
fi
else
echo "Refusing to delete branches that are not merged into ''$branch_name''. Checkout master first."
fi
Pruebe el siguiente comando:
git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))
Al utilizar git rev-parse
obtendrá el nombre de la rama actual para excluirlo. Si recibió el error, eso significa que no hay sucursales locales para eliminar.
Para hacer lo mismo con las sucursales remotas (cambiar el origin
con 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 varios controles remotos, agregue grep origin |
Antes del cut
para filtrar solo el origin
.
Si el comando anterior falla, primero intente eliminar las ramas de seguimiento remoto fusionadas:
git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))
Luego git fetch
vuelve a git fetch
el control remoto y usa el comando git push -vd
anterior nuevamente.
Si lo usa con frecuencia, considere agregar como alias a su archivo ~/.gitconfig
.
En caso de que hayas eliminado algunas ramas por error, usa git reflog
para encontrar las confirmaciones perdidas.
Puedes agregar el commit a la opción --merged. De esta manera, puede asegurarse solo de eliminar las ramas que se fusionan en, por ejemplo, el origen / maestro
El siguiente comando eliminará las ramas fusionadas de tu 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 --delete with echo
git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
Puedes usar la tool git-del-br
.
git-del-br -a
Puedes instalarlo vía pip
usando
pip install git-del-br
PD: Soy el autor de la herramienta. Cualquier sugerencia / retroalimentación es bienvenida.
Querrá excluir el master
y develop
ramas de 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
Script Python amigable con Windoze (porque git-sweep
ahogó en el repositorio de Wesnoth):
#!/usr/bin/env python
# Remove merged git branches. Cross-platform way to execute:
#
# git branch --merged | grep -v master | xargs git branch -d
#
# Requires gitapi - https://bitbucket.org/haard/gitapi
# License: Public Domain
import gitapi
repo = gitapi.Repo(''.'')
output = repo.git_command(''branch'', ''--merged'').strip()
for branch in output.split(''/n''):
branch = branch.strip()
if branch.strip('' *'') != ''master'':
print(repo.git_command(''branch'', ''-d'', branch).strip())
Si desea eliminar todas las sucursales locales que ya están fusionadas en la sucursal en la que se encuentra actualmente, se me ocurre 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 te dirá lo que está haciendo antes de hacerlo, usando la marca -t de xargs.
Si está utilizando un modelo de bifurcación como HubFlow o GitFlow, puede usar este comando para eliminar las ramas de características fusionadas:
git branch --merged | grep feature.* | grep -v "/*" | xargs -n 1 git branch -d
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 puedes eliminar todas las sucursales locales fusionadas haciendo una git cleanup
simple de git cleanup
.
Usando Git versión 2.5.0:
git branch -d `git branch --merged`
Uso el siguiente script de Ruby para eliminar mis sucursales locales y remotas ya fusionadas. Si lo hago para un repositorio con varios controles remotos y solo quiero eliminar de uno, solo agrego una declaración de selección 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
Utilizo un esquema de nombres de esque de git-flow, así 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 combinadas que comiencen con una fix/
cadena fix/
o feature/
.
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, vea esta respuesta para obtener consejos útiles sobre cómo escapar de alias complejos.
Git Sweep hace un gran trabajo de esto.
git branch --merged | grep -Ev ''^(. master|/*)'' | xargs -n 1 git branch -d
git branch --merged | grep -Ev ''^(. master|/*)'' | xargs -n 1 git branch -d
eliminará todas las sucursales locales, excepto la actual y / o la master
actual.
Aquí hay un artículo útil para aquellos que buscan entender estos comandos: Git Clean: eliminar ramas ya fusionadas, por Steven Harman .