Comment puis-je supprimer toutes les branches Git qui ont été fusionnées?
j'ai beaucoup de branches Git. Comment supprimer des branches qui ont déjà été fusionnées? Est-il un moyen facile de supprimer tous au lieu de les supprimer un par un?
30 réponses
mise à jour:
vous pouvez ajouter d'autres branches pour exclure comme maître et dev si votre flux de travail a ceux comme un ancêtre possible. En général, je me sépare d'une étiquette "sprint-start" et master, dev et qa ne sont pas des ancêtres.
pour supprimer toutes les succursales locales qui sont déjà fusionnées dans la succursale actuellement cochée:
git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d
vous pouvez voir que maître et dev sont exclus dans le cas où ils sont un ancêtre.
vous pouvez supprimer une branche locale fusionnée avec:
git branch -d branchname
si elle n'est pas fusionnée, utiliser:
git branch -D branchname
pour le supprimer de la télécommande dans les anciennes versions de Git use:
git push origin :branchname
Dans les versions plus récentes de Git:
git push --delete origin branchname
une fois que vous supprimez la branche de la télécommande, vous pouvez prendre pour se débarrasser des branches de suivi à distance avec:
git remote prune origin
ou prune individuelle de suivi à distance des branches, comme l'autre réponse suggère, avec:
git branch -dr branchname
Espérons que cette aide.
pour supprimer toutes les branches sur la télécommande qui sont déjà fusionnées:
git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin
dans les versions plus récentes de Git
git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin
Juste s'étendant Adam répondre un peu:
ajoutez ceci à votre configuration Git en exécutant git config -e --global
[alias]
cleanup = "!git branch --merged | grep -v '\*\|master\|develop' | xargs -n 1 git branch -d"
et ensuite vous pouvez supprimer toutes les branches locales fusionnées en faisant un simple git cleanup
.
cela fonctionne aussi pour supprimer toutes les branches fusionnées sauf master.
git branch --merged | grep -v '^* master$' | grep -v '^ master$' | xargs git branch -d
vous voudrez exclure les branches master
et develop
de ces commandes.
git Local clair:
git branch --merged | grep -v '\*\|master\|develop' | xargs -n 1 git branch -d
Distant git clair:
git branch -r --merged | grep -v '\*\|master\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin
Sync registre local des branches distantes:
git fetch -p
pour ceux d'entre vous qui sont sur Windows et préfèrent les scripts PowerShell, en voici un qui supprime les branches locales fusionnées:
function Remove-MergedBranches
{
git branch --merged |
ForEach-Object { $_.Trim() } |
Where-Object {$_ -NotMatch "^\*"} |
Where-Object {-not ( $_ -Like "*master" )} |
ForEach-Object { git branch -d $_ }
}
vous pouvez ajouter le commit à l'option --merged. De cette façon, vous pouvez vous assurer seulement pour enlever les branches qui sont fusionnées dans i.e. l'origine/maître
la commande suivante supprimera les branches fusionnées de votre origine.
git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 git push origin --delete
vous pouvez tester quelles branches seront enlevées en remplaçant l'origine git push --supprimer par echo
git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
utilisant la version 2.5.0 de Git:
git branch -d `git branch --merged`
j'utilise le script Ruby suivant pour supprimer mes branches locales et distantes déjà fusionnées. Si je le fais pour un dépôt avec plusieurs télécommandes et que je ne veux supprimer qu'une seule, je n'ai qu'à ajouter une instruction select à la liste des télécommandes pour obtenir seulement les télécommandes que je veux.
#!/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
kuboon la réponse de manquer de supprimer les branches qui ont le mot de maître dans le nom de la branche. Ce qui suit améliore sa réponse:
git branch -r --merged | grep -v "origin/master$" | sed 's/\s*origin\///' | xargs -n 1 git push --delete origin
bien sûr, il ne supprime pas la branche" master "elle-même:)
comment supprimer les branches fusionnées dans la console PowerShell
git branch --merged | %{git branch -d $_.Trim()}
voir GitHub for Windows
il n'y a aucune commande dans Git qui fera cela pour vous automatiquement. Mais vous pouvez écrire un script qui utilise des commandes Git pour vous donner ce dont vous avez besoin. Cela peut être fait de plusieurs façons selon ce ramification modèle que vous utilisez.
si vous avez besoin de savoir si une branche a été fusionnée dans master la commande suivante ne donnera aucun résultat si myTopicBranch a été fusionné (i.e. vous pouvez le supprimer)
$ git rev-list master | grep $(git rev-parse myTopicBranch)
vous pouvez utiliser le Git commandement de la branche et analyse Toutes les branches à Bash et faire une boucle for
sur toutes les branches. Dans cette boucle, vous vérifiez avec la commande ci-dessus, si vous pouvez supprimer la branche ou pas.
git branch --merged | grep -Ev '^(. master|\*)' | xargs -n 1 git branch -d
supprimera toutes les branches locales sauf la branche courante cochée et/ou master
.
Voici un article utile pour ceux qui cherchent à comprendre ces commandes: Git Clean: Supprime Déjà Fusionné les Branches, par Steven Harman .
J'utilise la réponse D'Adam depuis des années. Cela dit, il y a des cas où elle ne se comportait pas comme je l'espérais:
- branches que contenait le mot "master" a été ignoré, par exemple "notmaster" ou "masterful", plutôt que seulement la branche master
- branches que contenait le mot "dev" a été ignoré, par exemple "dev-test", plutôt que seulement la branche dev
- supprimer les branches qui sont accessibles à partir de la tête de la branche courante (c'est-à-dire, pas nécessairement maître)
- dans l'état de tête détaché, en supprimant chaque branche accessible à partir de la commit actuelle
1 & 2 étaient simples à traiter, avec juste un changement à la regex.
3 dépend du contexte de ce que vous voulez (c.-à-d. supprimer seulement les branches qui n'ont pas été fusionnées dans maître ou contre votre branche actuelle).
4 a le potentiel d'être désastreux (bien que récupérable avec git reflog
), si vous avez involontairement couru ce dans l'état de tête détaché.
enfin, je voulais que tout cela soit dans un seul liner qui ne nécessite pas de script séparé (Bash|Ruby|Python).
TL; DR
créer un git alias "sweep" qui accepte un drapeau optionnel -f
:
git config --global alias.sweep '!f(){ git branch --merged $([[ != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d; }; f'
et invoquez-le avec:
git sweep
ou:
git sweep -f
la réponse longue et détaillée
il était plus facile pour moi de créer un exemple git repo avec quelques branches et commits pour tester le comportement correct:
Créer un nouveau repo git avec un seul commit
mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"
Créer de nouvelles branches
git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list
bar develop foo * master masterful notmaster
comportement souhaité: sélectionner toutes les branches fusionnées sauf: master, develop ou current
le regex original manque les branches "masterful" et "notmaster":
git checkout foo
git branch --merged | egrep -v "(^\*|master|dev)"
bar
avec le regex mis à jour (qui exclut maintenant "développer" plutôt que" dev"):
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar masterful notmaster
passer à la branche foo, faire un nouveau commit, puis commander une nouvelle branche, foobar, basé sur foo:
echo "foo" > foo
git add . && git commit -am "foo"
git checkout -b foobar
echo "foobar" > foobar
git add . && git commit -am "foobar"
ma branche actuelle est foobar, et si je relance la commande ci-dessus pour lister les branches que je veux supprimer, la branche "foo" est incluse même si elle n'a pas été fusionnée dans master:
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar foo masterful notmaster
cependant, si je exécute la même commande sur le capitaine, la branche "foo" n'est pas incluse:
git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar masterful notmaster
et c'est simplement parce que git branch --merged
est par défaut à la tête de la branche courante, sauf indication contraire. Au moins pour mon workflow, Je ne veux pas supprimer les branches locales à moins qu'elles n'aient été fusionnées à master, donc je préfère la variante suivante:
git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
bar masterful notmaster
, Séparé de la TÊTE de l'état
S'appuyant sur le comportement par défaut de git branch --merged
git checkout foobar
git checkout HEAD~0
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar foo foobar masterful notmaster
Cela aurait supprimé la branche, j'étais juste sur, "foobar" avec "toto", qui est presque certainement pas le résultat souhaité. Avec notre commande révisée, cependant:
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
bar masterful notmaster
une ligne, y compris la ligne supprimer
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d
tous enveloppé dans un alias git "sweep":
git config --global alias.sweep '!f(){ git branch --merged $([[ != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d; }; f'
l'alias accepte un drapeau optionnel -f
. Le comportement par défaut est de supprimer uniquement les branches qui ont été fusionnées dans master, mais le drapeau -f
supprimera les branches qui ont été fusionnées dans la branche courante.
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).
vous pouvez utiliser git-del-br
outil .
git-del-br -a
vous pouvez l'installer via pip
en utilisant
pip install git-del-br
P. S: je suis l'auteur de l'outil. Toute suggestion ou rétroaction est la bienvenue.
Alias version de Adam de la mise à jour de réponse :
[alias]
branch-cleanup = "!git branch --merged | egrep -v \"(^\*|master|dev)\" | xargs git branch -d #"
voir Aussi cette réponse pour des conseils pratiques sur la fuite des complexes alias.
si vous souhaitez supprimer toutes les branches locales qui sont déjà fusionnées dans la branche sur laquelle vous êtes actuellement, alors j'ai trouvé une commande sûre pour le faire, basée sur les réponses précédentes:
git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d
cette commande n'affectera pas votre branche courante ni votre branche principale. Il vous dira aussi ce qu'il fait avant qu'il le fasse, en utilisant le drapeau-t de xargs.
essayez la commande suivante:
git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))
en utilisant git rev-parse
obtiendra le nom actuel de la branche afin de l'exclure. Si vous avez l'erreur, ce qui signifie qu'il n'y a pas de branches à supprimer.
pour faire la même chose avec les branches distantes (changer origin
avec votre nom distant), essayez:
git push origin -vd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD) | cut -d/ -f2)
dans le cas où vous avez plusieurs télécommandes, ajouter grep origin |
avant cut
pour filtrer seulement le origin
.
si la commande ci-dessus échoue, essayez de supprimer les branches fusionnées de suivi à distance en premier:
git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))
puis git fetch
la télécommande à nouveau et utilisez la commande précédente git push -vd
à nouveau.
si vous l'utilisez souvent, envisagez d'ajouter des alias dans votre fichier ~/.gitconfig
.
si vous avez enlevé des branches par erreur, utilisez git reflog
pour trouver les propagations Perdues.
basé sur certaines de ces réponses j'ai fait mon propre script Bash pour le faire aussi !
il utilise git branch --merged
et git branch -d
pour supprimer les branches qui ont été fusionnées et vous invite pour chacune des branches avant de supprimer.
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
}
j'utilise un système de nommage git-flow esque, donc cela fonctionne très sûrement pour moi:
git branch --merged | grep -e "^\s\+\(fix\|feature\)/" | xargs git branch -d
il cherche essentiellement des commits fusionnés qui commencent par la chaîne de caractères fix/
ou feature/
.
ci-dessous la requête fonctionne pour moi
for branch in `git branch -r --merged | grep -v '\*\|master\|develop'|awk 'NR > 0 {print}'|awk '{gsub(/origin\//, "")}1'`;do git push origin --delete $branch; done
et ceci filtrera n'importe quelle branche donnée dans le tuyau grep.
fonctionne bien sur le clone http, mais pas aussi bien pour la connexion ssh.
Écrire un script dans lequel Git vérifie toutes les branches qui ont été fusionnées à maîtriser.
puis git checkout master
.
enfin, supprimer les branches fusionnées.
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
la solution acceptée est assez bonne, mais il y a un problème qu'elle supprime aussi les branches locales qui n'ont pas encore été fusionnées dans une télécommande.
si vous regardez la sortie de vous verrez quelque chose comme
$ 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)
Branches bla
et issue_248
sont des branches locales qui seraient supprimées en silence.
mais vous pouvez aussi voir le mot [gone]
, qui indique les branches qui ont été poussées à une distance (qui est maintenant disparu) et donc dénoter des branches peuvent être supprimés.
la réponse originale peut donc être changée en (divisé en plusieurs lignes pour une longueur de ligne plus courte)
git branch --merged master -v | \
grep "\[gone\]" | \
sed -e 's/^..//' -e 's/\S* .*//' | \
xargs git branch -d
pour protéger les branches non encore fusionnées. Aussi le grêlage pour le maître pour le protéger, n'est pas nécessaire, car cela a une télécommande à l'origine et ne se présente pas comme disparu.
pour éviter d'exécuter accidentellement la commande d'une autre branche que master j'utilise le script bash suivant. Sinon, exécuter git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
à partir d'une branche fusionnée de off master pourrait supprimer la branche master.
#!/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
à partir de 2018.07
ajouter à [alias]
section de votre ~/.gitconfig
:
sweep = !"f() { git branch --merged | egrep -v \"(^\*|master|dev)\" || true | xargs git branch -d; }; f"
Maintenant, vous pouvez simplement appeler git sweep
pour effectuer ce nettoyage nécessaire.
Pour Windows, vous pouvez installer Cygwin et supprimer toutes les branches distantes en utilisant la commande suivante:
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
pour supprimer les branches locales qui ont été fusionnées à master branch j'utilise l'alias suivant ( git config -e --global
):
cleanup = "!git branch --merged master | grep -v '^*\|master' | xargs -n 1 git branch -D"
j'utilise git branch -D
pour éviter les messages error: The branch 'some-branch' is not fully merged.
alors que ma caisse actuelle est différente de la branche principale.
windoze-friendly Python script (parce que git-sweep
s'est étouffé sur le dépôt 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 vous utilisez un modèle de branchement comme HubFlow ou GitFlow, vous pouvez utiliser cette commande pour supprimer les branches fusionnées:
git branch --merged | grep feature.* | grep -v "\*" | xargs -n 1 git branch -d