Comment supprimer toutes les branches Git qui ont été fusionnées?

1936

J'ai de nombreuses succursales Git. Comment supprimer des branches qui ont déjà été fusionnées? Existe-t-il un moyen simple de les supprimer tous au lieu de les supprimer un par un?

Nyambaa
la source
46
Pour être un peu plus précis, vous git branch -Dsupprimez toute branche, qu'elle ait été fusionnée ou non.
PhilT
12
Vous pouvez également le faire directement depuis GitHub, si vous allez dans la section "branches" de votre référentiel (par exemple github.com/<username>/<repo_name>/branches ). Il devrait y avoir une liste de toutes vos branches, avec une icône de corbeille rouge sur le côté qui supprimera la branche sélectionnée. Beaucoup plus rapide que de le faire dans le terminal! Indiquera également dans quelle mesure masterchaque branche est en avance / en retard . Cependant, votre client local répertoriera toujours les anciennes branches si vous exécutez git branch -a; utiliser git fetch --prunepour les supprimer (selon cette réponse ).
user5359531
3
Script pour le faire localement ou à distance - avec des contrôles de sécurité et des «branches sûres» préconfigurées : github.com/fatso83/dotfiles/tree/master/utils/…git delete-merged --doit origin ougit delete-merged --doit --local
oligofren
Vous pouvez également utiliser cette application pour supprimer automatiquement les branches fusionnées.
Sebass van Boxel
rm -fr work && git clone http://example.com/work.gitau fil des ans est devenu le moyen le plus simple de sortir d'un cornichon avec git.
Reactgular

Réponses:

3117

MISE À JOUR:

Vous pouvez ajouter d'autres branches à exclure comme master et dev si votre flux de travail en a comme ancêtre possible. Habituellement, je dérive d'une balise "sprint-start" et master, dev et qa ne sont pas des ancêtres.

D'abord, répertoriez toutes les branches qui ont été fusionnées dans la télécommande.

git branch --merged

Vous pouvez voir quelques branches que vous ne souhaitez pas supprimer. nous pouvons ajouter quelques arguments pour ignorer les branches importantes que nous ne voulons pas supprimer comme master ou develop. La commande suivante sautera la branche principale et tout ce qui contient du dev.

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

Si vous souhaitez ignorer, vous pouvez l'ajouter à la commande egrep comme suit. La branche skip_branch_namene sera pas supprimée.

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

Pour supprimer toutes les branches locales déjà fusionnées dans la branche actuellement extraite:

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

Vous pouvez voir que master et dev sont exclus au cas où ils seraient un ancêtre.


Vous pouvez supprimer une branche locale fusionnée avec:

git branch -d branchname

S'il n'est pas fusionné, utilisez:

git branch -D branchname

Pour le supprimer de l'utilisation à distance:

git push --delete origin branchname

git push origin :branchname    # for really old git

Une fois que vous avez supprimé la branche de la télécommande, vous pouvez tailler pour vous débarrasser des branches de suivi à distance avec:

git remote prune origin

ou tailler les branches de suivi à distance individuelles, comme le suggère l'autre réponse, avec:

git branch -dr branchname

J'espère que cela t'aides.

Adam Dymitruk
la source
46
AVERTISSEMENT: si vous venez de créer une branche, elle sera également supprimée. Assurez-vous de ne pas avoir de branche nouvellement créée dans la liste avant d'exécuter la commande top most.
Gary Haran
154
CONTRE AVERTISSEMENT: reflog sauvera votre bacon. Alors ne t'inquiète pas.
Adam Dymitruk
33
Gardez à l'esprit que la première commande supprime uniquement les branches locales, elle n'est donc pas aussi «dangereuse» que certains l'ont souligné.
ifightcrime
79
Variante PowerShell, afin que je puisse la trouver ici la prochaine fois que j'ai googlé la réponse:git branch --merged | %{$_.trim()} | ?{$_ -notmatch 'develop' -and $_ -notmatch 'master'} | %{git branch -d $_}
vorou
23
Cela produit une erreur fatal: branch name requiredsi vous n'avez aucune branche à supprimer. Pour éviter cela, vous pouvez passer -rà xargsafin qu'il ne s'exécute pas git branch -dsi le stdin est vide. (Il s'agit d'une extension GNU xargs, selon la page de manuel).
Marius Gedminas
457

Pour supprimer toutes les branches distantes 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

MISE À JOUR (par @oliver; car ne tient pas dans le commentaire, mais suffisamment de réponses déjà) : si vous êtes sur la branche ABC, alors ABC apparaîtra dans les résultats git branch -r --mergedparce que la branche n'est pas spécifiée, donc la branche par défaut est la branche actuelle et une branche est toujours considéré comme fusionné avec lui-même (car il n'y a pas de différence entre une branche et elle-même!).

Donc, spécifiez la branche:

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

OU premier maître de caisse:

git checkout master | git branch -r --merged | grep -v ...
kuboon
la source
18
De loin la meilleure réponse. Juste une note, ma branche principale est nommée devdonc j'ai dû changer cela
Dorian
41
J'ai dû ajouter | grep originaprès grep -v masterpour éviter de pousser des branches d'autres télécommandes à l'origine. Je recommande fortement de tester la sortie au préalable, en utilisantgit branch -r --merged | grep -v master | grep origin | sed 's/origin\//:/' | xargs -n 1 echo
L0LN1NJ4
9
J'ai légèrement modifié pour exclure également la developbranche. git branch -r --merged | grep -v master | grep -v develop | sed 's/origin\///' | xargs -n 1 git push --delete origin. Maintenant, cela s'est avéré être mon alias.
Sarat
8
Ce qui en a fait la meilleure réponse que j'ai lue, c'est l' -rargument, que je n'ai vu nulle part ailleurs. Il est tenu pour acquis que seules les succursales locales valent la peine de faire le ménage. Mais les télécommandes sont également pleines d'ordures.
Asbjørn Ulsberg
19
Attention - vient de se rendre compte: cela va évidemment trouver des branches fusionnées avec la branche actuelle , pas master, donc si vous êtes dessus, myFeatureBranchelle s'effacera origin/myFeatureBranch. Il vaut probablement mieux git checkout mastercommencer.
jakub.g
190

Juste étendre un peu la réponse d'Adam:

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 puis vous pouvez supprimer toutes les branches locales fusionnées en faisant un simple git cleanup.

real_ate
la source
11
la première commande ne devrait-elle pas être: git branch --merged masterpuisque vous voulez regarder ce qui a été fusionné dans la branche principale, pas actuellement extraite?
Joe Phillips
@JoePhilllips Certaines personnes n'ont pas la branche principale mais à la place developou devet dans ce cas la commande échouera avec fatal: malformed object nameil vaut mieux avoir une commande générique et vous avez la responsabilité de l'exécuter
smohamed
1
@JoePhilllips le point de cette réponse est de regrouper la réponse d'Adam (la meilleure réponse à cette question) dans un alias git utile. La réponse d'Adam n'a pas ce que vous suggérez et tant de gens l'ont trouvé utile, donc je serais enclin à ne pas changer le mien. Je recommanderais d'ouvrir la discussion sur la réponse d'Adam si vous en êtes convaincu
real_ate
13
L'ajout -rà xargsévitera les erreurs inutiles ( branch name required) lors de l'exécution de cet alias plusieurs fois ou lorsqu'il ne reste aucune branche à supprimer. Mon alias ressemble à ceci:cleanup = "!git branch --merged | grep -v -P '^\\*|master|develop' | xargs -n1 -r git branch -d"
spezifanta
1
La commande actuelle ne filtre pas le maître et ne développe pas de branches
Andriy F.
83

Cela fonctionne également pour supprimer toutes les branches fusionnées à l'exception de master.

git branch --merged | grep -v '^* master$' | grep -v '^  master$' | xargs git branch -d
Ismael Abreu
la source
3
Maintenant, il ne supprimera aucune branche master. Essayez grep -v ^master$pour le milieu.
wchargin
Je laisserais également | grep -v '^\*'éviter de supprimer la branche actuelle si vous n'êtes pas sur master
svassr
5
C'est super, merci! Une mise en garde pour tous ceux qui utilisent ceci: notez qu'il y a deux espaces dedans grep -v '^ master$'. Si vous le saisissez vous-même et en manquez un, vous le supprimerez mastersi vous n'y êtes pas.
styger
3
@ Mr.Polywhirl votre modification rompt la commande et vous devez la rétablir. Les deux espaces sont nécessaires, car git branchlistera chaque nom de branche sur une nouvelle ligne avec deux espaces à gauche s'il ne s'agit pas de la branche actuellement extraite. Vous avez essentiellement garanti que toute personne qui exécute cette commande supprimera sa branche principale, sauf s'il s'agit de la branche actuellement extraite.
styger
79

Vous voudrez exclure les branches master& developde ces commandes.

Git local clair:

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

Git distant clair:

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

Synchroniser le registre local des succursales distantes:

git fetch -p
Guido Bouman
la source
3
+1 pour la version distante également (mais moins nécessaire car nous avons remote --prune). Notez également que thoose ne fonctionnera pas avec l'ancienne version git
malko
4
git config --global --add fetch.prune truepour tailler automatiquement lors de l'extraction ou de la traction.
T3rm1
1
Attention, le pruneau n'est pas la même chose que la télécommande claire. L'effacement à distance supprime en fait les branches distantes qui sont entièrement fusionnées avec votre branche actuelle. Prune nettoie uniquement votre registre local des branches distantes déjà supprimées.
Guido Bouman
Le mot est complètement un peu trompeur, car une branche sera considérée comme fusionnée, lorsqu'elle a été fusionnée auparavant, mais a de nouveaux commits après la fusion, qui n'ont pas été fusionnés.
scones
Pour supprimer toutes les télécommandes d'origine en un seul appel, j'ai utilisé ceci:git branch -r --merged | grep -v '\*\|master\|develop' | grep '^\s*origin/' | sed 's/origin\///' | tr "\n" " " | xargs git push --delete origin
GPHemsley
48

Pour ceux d'entre vous qui sont sous Windows et préfèrent les scripts PowerShell, voici celui qui supprime les branches fusionnées locales:

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}
Klas Mellbourn
la source
13
Par curiosité, cela peut être abrégé en git branch --merged | ?{-not ($_ -like "*master")} | %{git branch -d $_.trim()}
Iain Ballard
5
@IainBallard Bien sûr, j'aurais pu utiliser des alias. Ce n'est pas recommandé lorsque vous souhaitez maximiser la lisibilité. github.com/darkoperator/PSStyleGuide/blob/master/English.md
Klas Mellbourn
1
sûr. J'ai trouvé votre réponse très utile :-) Cependant, parfois, la syntaxe PowerShell de forme longue gêne ce qui se passe dans les blocs. Mais surtout, je proposais quelque chose que vous pourriez copier / coller ou taper comme une seule fois. Merci encore.
Iain Ballard,
4
Voici un shell liner pour Windows cmd qui préserve le master et votre branche actuelle: for /f "usebackq" %B in (``git branch --merged^|findstr /v /c:"* " /c:"master"``) do @git branch -d %B(soupir, remplacez les doubles-citations par des simples, je ne sais pas comment formater un littéral qui contient des backquotes)
yoyo
42

J'utilise la réponse d'Adam depuis des années maintenant. Cela dit, il y a des cas où il ne s'est pas comporté comme je m'y attendais:

  1. les branches qui contenaient le mot "master" ont été ignorées, par exemple "notmaster" ou "masterful", plutôt que seulement la branche master
  2. les branches qui contenaient le mot "dev" ont été ignorées, par exemple "dev-test", plutôt que seulement la branche dev
  3. suppression des branches accessibles depuis la TETE de la branche actuelle (c'est-à-dire pas nécessairement maître)
  4. dans l'état HEAD détaché, en supprimant toutes les branches accessibles depuis la validation actuelle

1 et 2 étaient simples à aborder, avec juste un changement de l'expression rationnelle. 3 dépend du contexte de ce que vous voulez (c.-à-d. Supprimer uniquement les branches qui n'ont pas été fusionnées en 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 l'avez involontairement exécuté en état HEAD détaché.

Enfin, je voulais que tout cela soit dans une seule ligne qui ne nécessite pas de script séparé (Bash | Ruby | Python).

TL; DR

Créez un "balayage" d'alias git qui accepte un -findicateur optionnel :

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

et l'invoquer avec:

git sweep

ou:

git sweep -f

La réponse longue et détaillée

Il m'a été plus facile de créer un exemple de dépôt git avec quelques branches et de valider le bon comportement:

Créer un nouveau dépôt git avec un seul commit

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

Créez de nouvelles succursales

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électionnez 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 la regex mise à jour (qui exclut désormais "développer" plutôt que "dev"):

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

Basculez vers la branche foo, faites un nouveau commit, puis extrayez une nouvelle branche, foobar, basée 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 réexécute la commande ci-dessus pour répertorier 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 j'exécute la même commande sur master, la branche "foo" n'est pas incluse:

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

Et c'est tout simplement parce que la valeur par git branch --mergeddéfaut est HEAD de la branche actuelle, sauf indication contraire. Au moins pour mon flux de travail, je ne veux pas supprimer les branches locales sauf si elles ont été fusionnées pour devenir 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

État HEAD détaché

S'appuyer sur le comportement par défaut de git branch --mergeda des conséquences encore plus importantes dans l'état HEAD détaché:

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 sur laquelle j'étais, "foobar" avec "foo", ce qui n'est 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 suppression réelle

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

Le tout enveloppé dans un alias git "sweep":

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

L'alias accepte un -findicateur facultatif . Le comportement par défaut consiste à supprimer uniquement les branches qui ont été fusionnées dans le maître, mais l' -findicateur supprimera les branches qui ont été fusionnées dans la branche actuelle.

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).
tourbillons
la source
Pourquoi avez-vous besoin de créer une fonction? N'est-ce pas git configatomique?
VasiliNovikov
Pour traiter l'argument optionnel «-f» (si je comprends bien votre question)
tourbillonne le
1
mais comment ça aide? Je veux dire le début de l'expression, !f(){ git branch .... C'est une déclaration de fonction, non? Pourquoi ne pas commencer directement avec git branch ...?
VasiliNovikov
1
Vous avez absolument raison. Modifié ma réponse en conséquence. Merci pour le pointeur!
remous
Les éléments suivants ne feraient-ils pas la même chose que le mode sans force? git checkout master && git branch -d `git branch --merged` && git checkout - Sauf que cela supprimerait develop, mais pourrait être une approche plus simple.
Guido Bouman
18

En utilisant Git version 2.5.0:

git branch -d `git branch --merged`
drautb
la source
16
Cela peut supprimer la masterbranche btw!
Wazery
4
Vrai. Je ne l'utilise que lorsque je suis sûr d'être allumé master.
drautb
11
git branch -d $(git branch --merged | grep -v master)
alexg
1
C'est dangereux si vous avez un flux, imaginez que vous avez le maître <- stage <- dev. La solution toujours la plus simple imo
Joseph Briggs
14

Vous pouvez ajouter le commit à l'option --merged. De cette façon, vous pouvez vous assurer de ne supprimer que les branches qui sont fusionnées, c'est-à-dire l'origine / master

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 les branches qui seront supprimées en remplaçant l'origine de git push - supprimer avec echo

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
Jörn Reimerdes
la source
2
J'aime l'option de test
iwein
12

J'utilise le script Ruby suivant pour supprimer mes branches locales et distantes déjà fusionnées. Si je le fais pour un référentiel avec plusieurs télécommandes et que je souhaite seulement en supprimer une, j'ajoute simplement une instruction select à la liste des télécommandes pour n'obtenir que 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
mmrobins
la source
Ça vous dérange si je vole cette friandise pour une petite bibliothèque d'aide git? github.com/yupiq/git-branch-util
logan
1
Allez-y, je ne l'aurais pas mis ici si je m'étais soucié que les gens réutilisent le code d'une manière ou d'une autre
mmrobins
@mmrobins Vous avez un extra \/au début de l'instruction de rejet pour la remote_branchesligne. Est-ce une faute de frappe ou sert-elle un but?
Jawwad
@mmrobins, oh tant pis, je vois la b.split(/\//)ligne maintenant
Jawwad
Si vous voulez faire cela fondamentalement mais via vanilla bash plutôt que ruby: stackoverflow.com/a/37999948/430128
Raman
11

Comment supprimer des branches fusionnées dans la console PowerShell

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

Si vous souhaitez exclure le maître ou tout autre nom de branche, vous pouvez diriger avec PowerShell Select-String comme ceci et transmettre le résultat à git branch -d:

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})
Konstantin Tarkus
la source
1
Des réponses plus élevées suggèrent le filtrage du maître ou d'autres branches. Pour ceux qui cherchent à le faire dans PowerShell: git branch --merged | findstr / v "master" | % {git branch -d $ _. trim ()}
tredzko
@tredzko Bon point. FTR, la réponse la plus élevée est stackoverflow.com/questions/6127328/… - vous pouvez republier votre commentaire avec celui lié et je le supprimerais ensuite
Ruben Bartelink
il essaie également de supprimer * master:)
iesen
9

la réponse de kuboon a manqué la suppression des branches qui ont le mot 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, cela ne supprime pas la branche "master" elle-même :)

Paras
la source
8

Il n'y a aucune commande dans Git qui le fera automatiquement pour vous. Mais vous pouvez écrire un script qui utilise les commandes Git pour vous donner ce dont vous avez besoin. Cela peut être fait de plusieurs manières selon le modèle de branchement que vous utilisez.

Si vous avez besoin de savoir si une branche a été fusionnée dans master, la commande suivante ne donnera aucune sortie si myTopicBranch a été fusionné (c'est-à-dire que vous pouvez la supprimer)

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

Vous pouvez utiliser la commande Git branch et analyser toutes les branches dans Bash et faire une forboucle sur toutes les branches. Dans cette boucle, vous vérifiez avec la commande ci-dessus si vous pouvez supprimer la branche ou non.

ralphtheninja
la source
7

Remarque : je ne suis pas satisfait des réponses précédentes (ne fonctionne pas sur tous les systèmes, ne fonctionne pas sur la télécommande, ne spécifie pas la branche --merged, ne filtre pas exactement). J'ajoute donc ma propre réponse.

Il existe deux cas principaux:

Local

Vous voulez supprimer des branches locales qui sont déjà fusionnées à une autre branche locale . Lors de la suppression, vous souhaitez conserver certaines branches importantes, comme master, develop, etc.

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

Remarques :

  • git branch output --format ".." consiste à supprimer les espaces blancs et à permettre une correspondance exacte avec grep
  • grep -Eest utilisé à la place de egrep , donc il fonctionne également dans les systèmes sans egrep (ie: git pour windows).
  • grep -E -v '^master$|^feature/develop$' est de spécifier les branches locales que je ne veux pas supprimer
  • xargs -n 1 git branch -d: effectuer la suppression des branches locales (cela ne fonctionnera pas pour les branches distantes)
  • bien sûr, vous obtenez une erreur si vous essayez de supprimer la branche actuellement extraite. Je suggère donc de passer au master au préalable.

Éloigné

Vous voulez supprimer des branches isolées qui sont déjà fusionnées à une autre branche à distance . Pendant la suppression, vous souhaitez conserver certaines branches importantes, comme 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

Remarques :

  • pour la télécommande, nous utilisons l' -roption et fournissons le nom complet de la branche :origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' est de faire correspondre les branches distantes que nous ne voulons pas supprimer.
  • cut -d/ -f2-: supprime le préfixe «origine /» inutile qui autrement est imprimé par la git branchcommande.
  • xargs -n 1 git push --delete origin : effectuer la suppression de branches distantes.
psuzzi
la source
7

Si vous êtes sous Windows, vous pouvez utiliser Windows Powershell ou Powershell 7 avec Out-GridView pour avoir une belle liste de branches et sélectionner avec la souris celle que vous souhaitez supprimer:

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

entrez la description de l'image ici après avoir cliqué sur OK, Powershell transmettra les noms de ces branches à la git branch -dcommande et les supprimera entrez la description de l'image ici

Mariusz Pawelski
la source
6

Vous pouvez utiliser l' git-del-br outil .

git-del-br -a

Vous pouvez l' installer via l' pipaide

pip install git-del-br

PS: je suis l'auteur de l'outil. Toutes suggestions / commentaires sont les bienvenus.

tusharmakkar08
la source
1
@ stackoverflow.com/users/100297/martijn-pieters : Pourquoi cette réponse a-t-elle été supprimée et rejetée?
tusharmakkar08
1
Votre réponse et votre outil ne fonctionnent pas. J'y passe quelques heures. Rien.
SpoiledTechie.com
@ SpoiledTechie.com: Pouvez-vous me dire à quel problème vous êtes confronté exactement? Je l'utilise régulièrement.
tusharmakkar08
Je peux partager une capture d'écran si vous souhaitez la mettre hors ligne? spoiledtechie à cette chose google mail. :)
SpoiledTechie.com
5

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 des réponses antérieures:

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

Cette commande n'affectera pas votre branche actuelle ou votre branche principale. Il vous indiquera également ce qu'il fait avant de le faire, en utilisant le drapeau -t de xargs.

chrismendis
la source
5

Version alias de la réponse mise à jour d' Adam :

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

Consultez également cette réponse pour obtenir des conseils pratiques sur l'échappement d'alias complexes.

Eliot
la source
5

J'utilise un schéma de dénomination git-flow esque, donc cela fonctionne en toute sécurité pour moi:

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

Il recherche essentiellement les validations fusionnées qui commencent par une chaîne fix/ou feature/.

Chad M
la source
4

Essayez la commande suivante:

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

En utilisant git rev-parse, vous obtiendrez le nom de la branche actuelle afin de l'exclure. Si vous obtenez l'erreur, cela signifie qu'il n'y a aucune branche locale à supprimer.

Pour faire de même avec les branches distantes (changez originavec votre nom de télécommande), essayez:

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

Si vous avez plusieurs télécommandes, ajoutez-les grep origin |avant cutpour filtrer uniquement les origin.

Si la commande ci-dessus échoue, essayez de supprimer d'abord les branches de suivi à distance fusionnées:

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

Puis git fetchà nouveau la télécommande et utilisez à git push -vdnouveau la commande précédente .

Si vous l'utilisez souvent, envisagez d'ajouter des alias dans votre ~/.gitconfigfichier.

Si vous avez supprimé certaines branches par erreur, utilisez git reflogpour rechercher les commits perdus.

kenorb
la source
4

Sur la base de certaines de ces réponses, j'ai fait mon propre script Bash pour le faire aussi !

Il utilise git branch --mergedet git branch -dpour supprimer les branches qui ont été fusionnées et vous invite à saisir chacune des branches avant de les 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
}
earlonrails
la source
4

La requête ci-dessous fonctionne pour moi

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

et cela filtrera n'importe quelle branche donnée dans le tube grep.

Fonctionne bien sur le clone http, mais pas si bien pour la connexion ssh.

user1460965
la source
4

En date du 2018.07

Ajoutez ceci à la [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 sweeppour effectuer le nettoyage nécessaire.

Sorin
la source
Pour moi, appeler git sweep ne répertorie que les branches qui doivent être nettoyées, mais cela ne les supprime pas
Victor Moraes
4

Sous Windows avec git bash installé egrep -v ne fonctionnera pas

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

grep -E -v est équivalent deegrep -v

Utilisez -dpour supprimer les branches déjà fusionnées ou -Dpour supprimer les branches non fusionnées

DevWL
la source
egrep -v fonctionne pour moi. J'utilise cependant gitbash du programme d'installation de gitextensions
Joe Phillips
4

J'ai utilisé la méthode suivante pour supprimer les branches locales ET distantes fusionnées dans un cmd.

J'ai les éléments suivants dans mon bashrcdossier:

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
}

source d' origine

Cela ne supprime pas la branche principale, mais supprime les branches locales ET distantes fusionnées . Une fois que vous avez cela dans votre fichier rc, lancez simplement rmb, une liste des branches fusionnées qui seront nettoyées et une confirmation de l'action s'affiche. Vous pouvez modifier le code pour ne pas demander de confirmation également, mais il est probablement bon de le conserver.

Prashant
la source
3

Écrivez un script dans lequel Git vérifie toutes les branches qui ont été fusionnées en master.

Alors fais git checkout master.

Enfin, supprimez 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
Komu
la source
3

La solution acceptée est assez bonne, mais a le seul problème qu'elle supprime également 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)

Les branches blaet issue_248sont des branches locales qui seraient supprimées en silence.

Mais vous pouvez également voir le mot [gone], qui indique que les branches qui avaient été poussées vers une télécommande (qui a maintenant disparu) et indiquent ainsi que les branches peuvent être supprimées.

La réponse originale peut ainsi être changée en (divisée en multiligne 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. De plus, il n'est pas nécessaire de demander au maître de le protéger, car il a une télécommande à l'origine et ne s'affiche pas comme disparu.

Heiko Rupp
la source
3

Pour moi, git branch --mergedne montre pas les branches qui ont été fusionnées via GitHub PR. Je ne suis pas sûr des raisons, mais j'utilise la ligne suivante pour supprimer toutes les branches locales qui n'ont pas de branche de suivi à distance :

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

Explication:

  • git branch --format "%(refname:short)" donne une liste des succursales locales
  • git branch -r | grep -v HEAD | cut -d/ -f2- donne une liste des branches distantes, filtrant HEAD
  • diff <(...) <(...) donne un diff de sortie de deux commandes entre parenthèses
  • grep '<' filtre les branches qui existent dans la première liste, mais pas dans la seconde
  • cut -c 3- donne une ligne à partir du 3ème caractère, supprimant ainsi le préfixe <
  • xargs git branch -Ds'exécute git branch -Dcontre chaque nom de branche

Alternativement, vous pouvez éviter grep -v '<'comme ceci:

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
la source