Existe-t-il un moyen simple de supprimer toutes les branches de suivi dont l'équivalent distant n'existe plus?
Exemple:
Succursales (locales et éloignées)
- Maître
- origine / maître
- origin / bug-fix-a
- origin / bug-fix-b
- origin / bug-fix-c
Localement, je n'ai qu'une branche maître. Maintenant, je dois travailler sur bug-fix-a , donc je le vérifie, je travaille dessus et je pousse les modifications sur la télécommande. Ensuite, je fais de même avec bug-fix-b .
Succursales (locales et éloignées)
- Maître
- bug-fix-a
- bug-fix-b
- origine / maître
- origin / bug-fix-a
- origin / bug-fix-b
- origin / bug-fix-c
J'ai maintenant le maître des branches locales , bug-fix-a , bug-fix-b . Le responsable de la branche Master fusionnera mes modifications dans Master et supprimera toutes les branches qu'il a déjà fusionnées.
Donc, l'état actuel est maintenant:
Succursales (locales et éloignées)
- Maître
- bug-fix-a
- bug-fix-b
- origine / maître
- origin / bug-fix-c
Maintenant, je voudrais appeler une commande pour supprimer les branches (dans ce cas bug-fix-a , bug-fix-b ), qui ne sont plus représentées dans le référentiel distant.
Ce serait quelque chose comme la commande existante git remote prune origin
, mais plus comme git local prune origin
.
la source
* master
sur mon système. La commande suivante a fonctionné pour moi:git branch -d $(git branch --merged |tail -n +2)
develop
alorsgit branch --merged
inclutmaster
! Vous ne voulez probablement pas (définitivement!) Supprimer cela. Je pense aussi que cela devrait êtregit branch -d
là où les minuscules-d
signifient "suppression sûre", par exemple, supprimer uniquement en cas de fusion.git branch --merged | grep -v "master" >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
Après la commande
supprime les références distantes, lorsque vous exécutez
il affichera «disparu» comme état à distance. Par exemple,
Vous pouvez donc écrire un script simple pour supprimer les branches locales qui sont devenues des télécommandes:
Notez que ce qui précède utilise la commande "porcelaine"
git branch
pour obtenir l'état en amont.Une autre façon d'obtenir ce statut est d'utiliser la commande "plomberie"
git for-each-ref
avec la variable d'interpolation%(upstream:track)
, qui sera[gone]
comme ci-dessus.Cette approche est quelque peu plus sûre, car il n'y a aucun risque de correspondance accidentelle sur une partie du message de validation.
la source
git branch -vv | gawk '{print $1,$4}' | grep 'gone]' | gawk '{print $1}'
awk '/: gone]/{if ($1!="*") print $1}'
. Cela fonctionne maintenant comme prévu.test = "!git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done"
La plupart de ces réponses ne répondent pas réellement à la question d'origine. Je l' ai fait un tas de creuser et c'était la solution que je propre trouvé. Voici une version légèrement plus approfondie de cette réponse:
git checkout master
git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d
Explication:
Fonctionne en élaguant vos branches de suivi, puis en supprimant celles locales qui montrent qu'elles sont "disparues"
git branch -vv
.Remarques:
Si votre langue est définie sur autre chose que l'anglais, vous devrez modifier
gone
le mot approprié. Les succursales locales ne seront pas touchées. Les branches qui ont été supprimées sur la télécommande mais qui n'ont pas été fusionnées afficheront une notification mais ne seront pas supprimées sur la locale. Si vous souhaitez également les supprimer, passez-d
à-D
.la source
git checkout master && ...
au début de la commande.git branch -vv
commencera par un astérisque qui finira par être exécutégit branch -d *
. Voici une version corrigée qui ignorera les lignes avec un astérisque:git branch -vv | grep ': gone]'| grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d
Je ne répondrais pas normalement à une question qui a déjà 16 réponses, mais toutes les autres réponses sont fausses, et la bonne réponse est si simple. La question dit: "Existe-t-il un moyen simple de supprimer toutes les branches de suivi dont l'équivalent distant n'existe plus?"
Si «simple» signifie les supprimer tous en une seule fois, ni fragiles, ni dangereux, et sans dépendre d'outils que tous les lecteurs n'auront pas, alors la bonne réponse est: non.
Certaines réponses sont simples, mais elles ne font pas ce qui a été demandé. D'autres font ce qui a été demandé, mais ne sont pas simples: tous reposent sur l'analyse de la sortie Git via des commandes de manipulation de texte ou des langages de script, qui peuvent ne pas être présents sur tous les systèmes. En plus de cela, la plupart des suggestions utilisent des commandes porcelaine, dont la sortie n'est pas conçue pour être analysée par script ("porcelaine" se réfère aux commandes destinées à une opération humaine; les scripts doivent utiliser les commandes "plomberie" de niveau inférieur).
Lectures complémentaires:
git branch
sortie dans un script .git remote prune
,git prune
,git fetch --prune
Si vous voulez le faire en toute sécurité, pour le cas d'utilisation de la question (branches de suivi de récupération de place qui ont été supprimées sur le serveur mais existent toujours en tant que branches locales) et avec des commandes Git de haut niveau uniquement, vous devez
git fetch --prune
(ougit fetch -p
, qui est un alias, ougit prune remote origin
qui fait la même chose sans aller chercher, et n'est probablement pas ce que vous voulez la plupart du temps).git branch -v
(toute branche de suivi orpheline sera marquée "[disparu]").git branch -d [branch_name]
sur chaque branche de suivi orpheline(ce que proposent certaines des autres réponses).
Si vous voulez
for-each-ref
créer un script pour une solution, alors est votre point de départ, comme dans la réponse de Mark Longair ici et cette réponse à une autre question , mais je ne vois pas de moyen de l'exploiter sans écrire une boucle de script shell, ou en utilisant xargs ou quelque chose .Explication du contexte
Pour comprendre ce qui se passe, vous devez comprendre que, dans le cas du suivi des succursales, vous n'avez pas une succursale, mais trois. (Et rappelez-vous que "branche" signifie simplement un pointeur vers une validation.)
Étant donné une branche de suivi
feature/X
, le référentiel distant (serveur) aura cette branche et l'appellerafeature/X
. Votre référentiel local a une brancheremotes/origin/feature/X
qui signifie: «Voici ce que la télécommande m'a dit que sa branche fonctionnalité / X était, la dernière fois que nous avons parlé», et enfin, le référentiel local a une branchefeature/X
qui pointe vers votre dernier commit et est configuré pour "Piste"remotes/origin/feature/X
, ce qui signifie que vous pouvez tirer et pousser pour les maintenir alignés.À un moment donné, quelqu'un a supprimé le
feature/X
sur la télécommande. A partir de ce moment, vous vous retrouvez avec votre localfeature/X
(dont vous ne voulez probablement plus, car le travail sur la fonctionnalité X est probablement terminé), et le vôtreremotes/origin/feature/X
est certainement inutile car son seul but était de se souvenir de l'état de la branche du serveur .Et Git vous permettra de nettoyer automatiquement les redondants
remotes/origin/feature/X
- c'est ce qui segit fetch --prune
passe - mais pour une raison quelconque, il ne vous permet pas de supprimer automatiquement les vôtresfeature/X
... même si votrefeature/X
contient toujours les informations de suivi orphelines, il contient donc les informations pour identifier les anciennes succursales de suivi qui ont été complètement fusionnées. (Après tout, il peut vous donner les informations qui vous permettent de faire l'opération vous-même à la main.)la source
xargs
). Il faut égalementgit alias
simplifier un certain nombre de cas.xargs
ou bash, et ils ne sont probablement pas ici à la recherche d'un défi de micro-codage, autant qu'une réponse rapide qu'ils peuvent appliquer en toute sécurité sans se distraire davantage de leur véritable objectif .J'ai trouvé la réponse ici: Comment puis-je supprimer toutes les branches git qui ont été fusionnées?
Assurez-vous que nous gardons le maître
Vous pouvez vous assurer que
master
, ou toute autre branche d'ailleurs, ne soit pas supprimée en en ajoutant une autregrep
après la première. Dans ce cas, vous iriez:Donc, si nous voulions garder
master
,develop
etstaging
par exemple, nous irions:Faites-en un alias
Comme il est un peu long, vous voudrez peut-être ajouter un alias à votre
.zshrc
ou.bashrc
. Le mien s'appellegbpurge
(pourgit branches purge
):Rechargez ensuite votre
.bashrc
ou.zshrc
:ou
la source
Solution Windows
Pour Microsoft Windows Powershell:
git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}
Explication
git checkout master
passe à la branche principalegit remote update origin --prune
élagage des branches éloignéesgit branch -vv
obtient une sortie détaillée de toutes les branches ( référence git )Select-String -Pattern ": gone]"
obtient uniquement les enregistrements où ils ont été supprimés de la télécommande.% { $_.toString().Trim().Split(" ")[0]}
obtenir le nom de la succursale% {git branch -d $_}
supprime la branchela source
.Trim()
après.toString()
pour supprimer deux espaces avant le nom de la branche.git branch -d
pourgit branch -D
sinon j'obtiens l'erreur la branche n'est pas complètement fusionnée.git branch -D
est destructeur et supprimera le travail local que vous n'avez pas encore poussé.-d
est toujours sûr, soyez prudent-D
.Le motif correspondant à «disparu» dans la plupart des autres solutions était un peu effrayant pour moi. Pour être plus sûr, cela utilise l'
--format
indicateur pour extraire l' état de suivi en amont de chaque branche .J'avais besoin d'une version compatible avec Windows, donc cela supprime toutes les branches répertoriées comme "disparues" à l'aide de Powershell:
La première ligne répertorie le nom des branches locales dont la branche en amont est "disparue". La ligne suivante supprime les lignes vides (qui sont sorties pour les branches qui ne sont pas "disparues"), puis le nom de la branche est passé à la commande pour supprimer la branche.
la source
--format
option semble être relativement nouvelle; J'avais besoin de mettre à niveau git de 2.10.quelque chose à 2.16.3 pour l'obtenir. Voici ma modification pour les systèmes Linux:git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" | sed 's,^refs/heads/,,' | grep . | xargs git branch -D
refname:short
. Ensuite, vous pouvez supprimer la ligne% { $_ -replace '^refs/heads/', '' }
git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | where { $_ -ne "" } | foreach { git branch -d $_ }
Aussi probablement une bonne idée d'utiliser à la-d
place de-D
. La suppression forcée ne devrait pas être nécessaire pour les branches qui ne sont plus sur la télécommande.Supprimez toutes les branches qui ont été fusionnées dans master, mais n'essayez pas de supprimer master lui-même:
git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)
ou ajoutez un alias:
alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"
Explication:
git checkout master
caisse principale de caissegit pull origin master
s'assurer que la succursale locale a fusionné toutes les modifications à distancegit fetch -p
supprimer les références aux branches distantes qui ont été suppriméesgit branch -d $(git branch master --merged | grep master -v)
supprimez toutes les branches qui ont été fusionnées en master, mais n'essayez pas de supprimer le master lui-mêmela source
git branch -D
commandegit branch -d
qui devraient émettre un avertissement sur les branches non poussées.Cela élagera toutes les branches qui n'existent plus sur la télécommande.
la source
X
; vousgit checkout X
; maintenant votre dépôt a une branche de suivi (locale)X
et une branche distanteorigin/X
; le référentiel distant supprimeX
; vousgit fetch-p
; dans votre référentiel local, non seulementorigin/X
mais aussiX
ont été supprimés. C'est ce que vous dites?Encore une autre réponse pour la pile, s'inspirant largement de la réponse de Patrick (que j'aime parce qu'elle semble éliminer toute ambiguïté sur l'endroit où
gone]
correspondra legit branch
sortie) mais en ajoutant un * nix plié.Dans sa forme la plus simple:
Je l'ai enveloppé dans un
git-gone
script sur mon chemin:NB - Le
--format
option semble assez récente; J'avais besoin de mettre à niveau git de 2.10.quelque chose à 2.16.3 pour l'obtenir.EDIT: ajusté pour inclure une suggestion
refname:short
de Benjamin W.NB2 - J'ai seulement testé en
bash
, d'où le hashbang, mais probablement portablesh
.la source
sed
partie en utilisant%(refname:short)
dans la première ligne?--format
. Une autre façon de sauter lased
partie est d'utilisergit update-ref -d
. Notez que cela est probablement quelque peu dangereux, l'utilisationgit for-each-ref
est plus sûre ici (donnée--shell
).--format
pour le faire moi-même. Juste une question: pourquoi le#!bash
? Tout icish
me semble portable .Pourrait être utile à certains, une seule ligne simple pour effacer toutes les succursales locales sauf master et develop
la source
'git branch | grep -v "master" | grep -v "develop"
genre de choses avant de s'engager à ajouter la partie suppression de la commande. 👏😊Cela supprimera toutes les branches locales fusionnées, à l'exception de la référence principale locale et de celle actuellement utilisée:
Et cela supprimera toutes les branches ayant déjà été supprimées du référentiel distant référencé par " origine ", mais sont toujours disponibles localement dans " télécommandes / origine ".
la source
git branch -vv | grep 'gone]' | grep -v "\*" | awk '{print $1}' | xargs -r git branch -d
Explication: je préfère remplacer legit branch --merged
pargit branch -vv
pour afficher le statut (disparu) car le précédentgit branch --merged
peut également montrer le maîtreJe ne pense pas qu'il existe une commande intégrée pour ce faire, mais il est sûr de faire ce qui suit:
Lorsque vous utilisez
-d
, git refusera de supprimer la branche à moins qu'elle ne soit complètement fusionnée dansHEAD
ou sa branche de suivi à distance en amont. Ainsi, vous pouvez toujours parcourir la sortie degit for-each-ref
et essayer de supprimer chaque branche. Le problème avec cette approche est que je soupçonne que vous ne voulez probablement pasbug-fix-d
être supprimé simplement parce qu'ilorigin/bug-fix-d
contient son historique. Au lieu de cela, vous pouvez créer un script quelque chose comme ceci:Attention: je n'ai pas testé ce script - à n'utiliser qu'avec précaution ...
la source
TL; DR:
Supprimez TOUTES les succursales locales qui ne sont pas distantes
Supprimez TOUTES les branches locales qui ne sont pas distantes ET qui sont entièrement fusionnées ET qui ne sont pas utilisées comme indiqué dans de nombreuses réponses auparavant.
Explication
git fetch -p
va tailler toutes les branches qui n'existent plus sur la télécommandegit branch -vv
imprimera les branches locales et les branches élaguées seront étiquetées avecgone
grep ': gone]'
sélectionne uniquement la branche disparueawk '{print $1}'
filtrer la sortie pour afficher uniquement le nom des branchesxargs git branch -D
fera une boucle sur toutes les lignes (branches) et forcera la suppression de cette branchePourquoi
git branch -D
et pasgit branch -d
autre chose pour les succursales qui ne sont pas complètement fusionnées.la source
Vous pouvez faire ceci:
la source
Sur la base des informations ci-dessus, cela a fonctionné pour moi:
Il supprime toutes les succursales locales qui sont
': gone] '
distantes.la source
gone
n'importe où dans son nom.La commande ci-dessus peut être utilisée pour récupérer des branches qui sont fusionnées et supprimées dans la télécommande et elle supprime la branche locale qui n'est plus disponible dans la télécommande
la source
grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -D
pour forcer la suppression de toutgone
n'importe où (par exempleusingonefunction
).Rien de tout cela ne me convenait vraiment. Je voulais quelque chose qui purgerait toutes les branches locales qui suivaient une branche distante, sur
origin
, où la branche distante a été supprimée (gone
). Je ne voulais pas supprimer les branches locales qui n'avaient jamais été configurées pour suivre une branche distante (c'est-à-dire mes branches de développement locales). Je voulais aussi un simple one-liner qui utilise simplementgit
, ou d'autres outils CLI simples, plutôt que d'écrire des scripts personnalisés. J'ai fini par utiliser un peu degrep
etawk
pour faire cette commande simple.C'est finalement ce qui s'est terminé dans mon
~/.gitconfig
:Voici une
git config --global ...
commande pour ajouter facilement ceci commegit prune-branches
:REMARQUE: Dans la commande config, j'utilise l'
-d
optiongit branch
plutôt que-D
, comme je le fais dans ma configuration réelle. J'utilise-D
parce que je ne veux pas entendre Git se plaindre de branches non fusionnées. Vous pouvez également souhaiter cette fonctionnalité. Si c'est le cas, utilisez simplement-D
plutôt-d
qu'à la fin de cette commande de configuration.la source
git branch -vv
et chercher: gone]
et ne pas fairegit branch -v
et ne pas vouloir[gone]
?v
. Sigit branch -v | grep '[gone]'
ça marche pour vous, allez-y. Cela semble un peu plus propre.Basé sur Git Tip: Deleting Old Local Branches , qui ressemble à la solution de jason.rickman, j'ai implémenté une commande personnalisée à cet effet appelée git gone using Bash:
git gone -pn
combine l'élagage et la liste des branches "disparues":Ensuite, vous pouvez appuyer sur la gâchette à l'aide de
git gone -d
ougit gone -D
.Remarques
"$BRANCH/.*: gone]"
où$BRANCH
serait normalementorigin
. Cela ne fonctionnera probablement pas si votre sortie Git est localisée en français, etc.la source
git gone
ressemble à un alias pourgit branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d
, ce qui résout le problème du PO.S'inspirant largement d'un certain nombre d' autres réponses ici, je me suis retrouvé avec ce qui suit (git 2.13 et supérieur uniquement, je crois), qui devrait fonctionner sur n'importe quel shell de type UNIX:
Cela utilise notamment
for-each-ref
au lieu debranch
(commebranch
c'est une commande "porcelaine" conçue pour une sortie lisible par l'homme, pas un traitement machine) et utilise son--shell
argument pour obtenir une sortie correctement échappée (cela nous permet de ne nous soucier d'aucun caractère dans le nom de la référence).la source
[ ! -z "$ref" ]
signifie. Je pense qu'un multi liner aurait déjà aidé. Mais merci encore pour votre contribution!Encore une autre réponse, car aucune des solutions ne répond à mes besoins d'élégance et de multiplateforme:
Commande pour supprimer les branches locales non distantes:
Pour l'intégrer à gitconfig afin qu'il puisse être exécuté avec
git branch-prune
:Frapper
PowerShell
(Besoin d'aide pour trouver une commande universelle pour PowerShell et bash)
Pourquoi cette réponse est la meilleure?
git branch-prune
commande à votre gitgit for-each-ref
--filter
aucune dépendance externe requiseExplication:
~\.gitconfig
. Après avoir exécuté cela, vous pouvez simplement fairegit branch-prune
--prune
drapeau, qui "taille les branches de suivi à distance qui ne sont plus à distance"git for-each-ref
et--filter
, pour obtenir une liste des branches sont[gone]
(pas de télécommande)la source
Je suis venu avec ce script bash. Il garde toujours les branches
develop
,qa
,master
.la source
J'utilise une méthode courte pour faire le tour, je vous recommande de faire de même car cela pourrait gagner quelques heures et vous donner plus de visibilité
Ajoutez simplement l'extrait suivant dans votre .bashrc (.bashprofile sur macos).
Vous devrez éditer la regex grep afin de l'adapter à vos besoins (ici, cela empêche la suppression de master, preprod et dmz)
la source
git fetch --all --prune
a fait l'affaire. Merci!Cela a fonctionné pour moi:
la source
Je ne sais pas pour combien de temps, mais j'utilise git-up maintenant, qui s'en occupe.
Je le fais
git up
et il commence à suivre les nouvelles branches et supprime les anciennes.Juste pour être clair, ce n'est pas une commande git prête à l'emploi - https://github.com/aanand/git-up
BTW, il cache également un arbre sale et fait des rebases toujours avec juste
git up
.J'espère que ça sera utile pour quelqu'un
la source
Voici une solution que j'utilise pour la coquille de poisson. Testé sur
Mac OS X 10.11.5
,fish 2.3.0
etgit 2.8.3
.Quelques notes:
Assurez-vous de régler le bon
base_branch
. Dans ce cas, j'utilisedevelop
comme branche de base, mais cela pourrait être n'importe quoi.Cette partie est très importante:
grep -v "\(master\|$base_branch\|\*\)"
. Il garantit que vous ne supprimez pas le maître ou votre branche de base.J'utilise
git branch -d <branch>
comme une précaution supplémentaire, afin de ne pas supprimer toute branche qui n'a pas été complètement fusionnée avec HEAD en amont ou actuelle.Un moyen facile de tester est de le remplacer
git branch -d $f
parecho "will delete $f"
.Je suppose que je devrais également ajouter: UTILISER À VOS PROPRES RISQUES!
la source
J'ai écrit un script Python en utilisant GitPython pour supprimer les branches locales qui n'existent pas à distance.
J'espère que quelqu'un le trouvera utile, veuillez ajouter des commentaires si j'ai raté quelque chose.
la source
Si vous utilisez
zsh
shell avecOh My Zsh
installé, la façon la plus simple de le faire en toute sécurité est d'utiliser la saisie semi-automatique intégrée.Déterminez d'abord les branches que vous souhaitez supprimer avec:
cela vous montrera une liste des branches déjà fusionnées
Une fois que vous en connaissez quelques-uns que vous souhaitez supprimer, tapez:
Tout ce que vous avez à faire est d'appuyer sur [tab] et il vous montrera une liste des succursales locales. Utilisez tab-complete ou appuyez simplement sur [tab] à nouveau et vous pouvez les parcourir pour sélectionner une branche avec [enter].
Onglet Sélectionnez les branches encore et encore jusqu'à ce que vous ayez une liste de branches que vous souhaitez supprimer:
Maintenant, appuyez simplement sur Entrée pour supprimer votre collection de branches.
Si vous n'utilisez pas zsh sur votre terminal ... Téléchargez-le ici.
la source
J'aime utiliser des tuyaux car cela rend la commande plus facile à lire.
C'est ma solution si vous souhaitez supprimer toutes les branches sauf master.
Pour supprimer d'autres branches correspondant à vos critères, modifiez le premier et le deuxième bloc.
la source
Voici la réponse simple qui a fonctionné pour moi en utilisant un client git:
Supprimez complètement le référentiel de votre ordinateur, puis vérifiez à nouveau.
Pas de détournement avec des scripts risqués.
la source