web-dev-qa-db-fra.com

Comment supprimer les branches de suivi locales qui n'existent plus sur une télécommande

Avec git remote Prune Origin, je peux supprimer les branches locales qui ne sont plus sur la télécommande.

Mais je veux aussi supprimer les branches locales qui ont été créées à partir de ces branches distantes (vérifier si elles sont non fusionnées serait bien).

Comment puis-je faire ceci?

522
Alex

Après la taille, vous pouvez obtenir la liste des branches distantes avec git branch -r. La liste des branches avec leur branche de suivi à distance peut être récupérée avec git branch -vv. Donc, en utilisant ces deux listes, vous pouvez trouver les branches de suivi à distance qui ne figurent pas dans la liste des télécommandes.

Cette ligne devrait faire l'affaire (nécessite bash ou zsh, ne fonctionnera pas avec Bourne Shell standard):

git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep Origin) | awk '{print $1}' | xargs git branch -d

Cette chaîne obtient la liste des branches distantes et la transmet à egrep via l'entrée standard. Et filtre les branches qui ont une branche de suivi à distance (en utilisant git branch -vv et en filtrant celles qui ont Origin) puis en obtenant la première colonne de cette sortie qui sera le nom de la branche. Enfin, en passant tous les noms de branches dans la commande delete branch.

Comme il utilise l'option -d, il ne supprimera pas les branches qui n'ont pas été fusionnées dans la branche sur laquelle vous vous trouvez lorsque vous exécutez cette commande.

Rappelez-vous également que vous devrez exécuter git fetch --Prunepremier, sinon git branch -r verra toujours les branches distantes.

747
Schleis

Si vous souhaitez supprimer toutes les branches locales déjà fusionnées dans le maître, vous pouvez utiliser la commande suivante:

git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d

Plus d'informations .

324
jackocnr

Parmi les informations présentées par git help fetch, il y a ce petit article:

 -p, --Prune
        After fetching, remove any remote-tracking branches which no longer exist on the remote.

Alors, peut-être que git fetch -p est ce que vous cherchez?

EDIT: Ok, pour ceux qui débattent encore de cette réponse trois ans après les faits, voici un peu plus d’informations sur les raisons pour lesquelles j’ai présenté cette réponse ...

Premièrement, le PO dit vouloir "supprimer également les branches locales créées à partir de ces branches distantes [qui ne sont plus sur la télécommande]". Ce n'est pas possible sans ambiguïté dans git. Voici un exemple.

Supposons que j'ai un dépôt sur un serveur central et qu'il comporte deux branches, appelées A et B. Si je clone ce référentiel sur mon système local, mon clone aura des références locales (pas encore de branches réelles) appelées Origin/A et Origin/B. Maintenant, disons que je fais ce qui suit:

git checkout -b A Origin/A
git checkout -b Z Origin/B
git checkout -b C <some hash>

Les faits pertinents ici sont que, pour une raison quelconque, j'ai choisi de créer une branche sur mon référentiel local qui porte un nom différent de celui de son origine et j'ai également une branche locale qui n'existe pas (encore) sur le référentiel Origin.

Supposons maintenant que je supprime les branches A et B du référentiel distant et mette à jour mon référentiel local (git fetch d'une forme), ce qui entraîne la disparition de mes références locales Origin/A et Origin/B. À présent, mon référentiel local a encore trois branches, A, Z et C. Aucun d'entre eux n'a de branche correspondante sur le référentiel distant. Deux d'entre eux ont été "créés à partir de ... branches distantes", mais même si je sais qu'il existait auparavant une branche appelée B sur l'Origine, je n'ai aucun moyen de savoir que Z a été créé à partir de B, car elle a été renommée en le processus, probablement pour une bonne raison. Ainsi, vraiment, sans métadonnées d’origine de branche d’enregistrement de processus externes, ou un humain connaissant l’historique, il est impossible de déterminer laquelle des trois branches, le cas échéant, est ciblée par le PO pour suppression. Sans certaines informations externes que git ne conserve pas automatiquement pour vous, git fetch -p est aussi proche que possible, et toute méthode automatique permettant de tenter littéralement ce que l'OP a demandé risque de supprimer trop de branches ou d'en omettre certaines que l'OP voudrait sinon supprimé.

Il existe également d'autres scénarios, par exemple si je crée trois branches distinctes de Origin/A pour tester trois approches différentes, puis que Origin/A disparaît. Maintenant, j'ai trois branches, qui ne peuvent évidemment pas correspondre au nom, mais elles ont été créées à partir de Origin/A, et donc une interprétation littérale de la question des PO nécessiterait de supprimer les trois. Cependant, cela peut ne pas être souhaitable, si vous pouviez même trouver un moyen fiable de les assortir ...

130
twalberg

Cela supprimera les branches locales pour lesquelles les branches de suivi à distance ont été élaguées. (Assurez-vous d'être sur une branche master!)

git checkout master
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -d

Détails: 

  • git branch -vv affiche "disparu" pour les branches locales pour lesquelles la télécommande a été élaguée.

    mybranch abc1234 [Origin/mybranch: gone] commit comments
    
  • -d vérifiera s'il a été fusionné (-D le supprimera quand même)

    error: The branch 'mybranch' is not fully merged.
    
88
wisbucky

On peut configurer Git pour supprimer automatiquement les références aux branches distantes supprimées lors de la récupération:

git config --global fetch.Prune true

Lors de l'appel ultérieur de git fetch ou git pull, les références aux branches distantes supprimées sont automatiquement supprimées.

38
wedesoft

Il répertorie les branches locales dont la branche de suivi à distance est supprimée

$ git remote Prune Origin --dry-run

Si vous souhaitez dé-référencer ces branches locales des branches locales non suivies

$ git remote Prune Origin
21
027

Il existe un paquetage NPM soigné qui le fait pour vous (et il devrait fonctionner sur plusieurs plates-formes).

Installez-le avec: npm install -g git-removed-branches

Ensuite, git removed-branches vous montrera toutes les branches locales obsolètes et git removed-branches --Prune pour les supprimer.

Plus d'infos ici.

20
tzachs

Si vous utilisez Windows et Powershell, vous pouvez utiliser ce qui suit pour supprimer toutes les branches locales fusionnées dans la branche actuellement extraite:

git branch --merged | ? {$_[0] -ne '*'} | % {$_.trim()} | % {git branch -d $_}

Explication

  • Répertorie la branche actuelle et les branches qui ont été fusionnées dans celle-ci.
  • Filtre la branche actuelle
  • Nettoie tous les espaces de début et de fin de la sortie git pour chaque nom de branche restant
  • Supprime les branches locales fusionnées

Cela vaut la peine de lancer git branch --merged tout seul pour s’assurer que cela ne fera que supprimer ce que vous attendez.

(Porté/automatisé depuis http://railsware.com/blog/2014/08/11/git-Housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/ . )

15
Gnat

Je voulais quelque chose qui purge toutes les branches locales qui suivaient une branche distante, le 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). De plus, je voulais une ligne simple qui utilise simplement git ou d'autres outils CLI simples, plutôt que d'écrire des scripts personnalisés. J'ai fini par utiliser un peu de grep et awk pour créer cette commande simple, puis je l'ai ajouté comme alias dans mon ~/.gitconfig

[alias]
  Prune-branches = !git remote Prune Origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D

Voici une commande git config --global ... pour l'ajouter facilement en tant que git Prune-branches:

git config --global alias.Prune-branches '!git remote Prune Origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'

REMARQUE: L'utilisation de l'indicateur -D avec git branch peut être très dangereuse. Donc, dans la commande config ci-dessus, j'utilise l'option -d pour git branch plutôt que -D; J'utilise -D dans ma configuration actuelle. J'utilise -D parce que je ne veux pas entendre Git se plaindre des branches non encore fusionnées, je veux juste qu'elles s'en aillent. Vous voudrez peut-être aussi cette fonctionnalité. Si c'est le cas, utilisez simplement -D au lieu de -d à la fin de cette commande de configuration.

7
Karl Wilbur

Un one-liner encore plus court et plus sûr:

git branch -d $(git branch --merged | cut -c 3-)

Assurez-vous de passer à la branche qui n'est pas encore fusionnée avant de l'exécuter. Parce que vous ne pouvez pas supprimer la branche sur laquelle vous êtes actuellement enregistré.

5
FelikZ

vous ne savez pas comment tout faire en même temps, mais git git branch -d <branchname> ne supprimera une branche locale que si elle est complètement fusionnée. Notez la minuscule d.

git branch -D <branchname> (notez le D majuscule) supprimera une succursale locale, quel que soit son statut fusionné.

4
NHDaly

Pour supprimer des branches distantes

$git remote Prune Origin

Pour supprimer des branches locales déjà fusionnées

$git branch -D $(git branch --merged)
2
Aniket

Sur la base des réponses ci-dessus, je suis arrivé avec cette solution en une ligne:

git remote Prune Origin; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep Origin) | awk '{print $1}' | xargs git branch -d
2
gagarwal

Vous pouvez utiliser cette commande:

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

Git Clean: supprime les branches déjà fusionnées , y compris la panne

2
sendon1982

En utilisant une variante de la réponse de @ wisbucky, j'ai ajouté ce qui suit comme alias à mon fichier ~/.gitconfig:

pruneitgood = "!f() { \
    git remote Prune Origin; \
    git branch -vv | Perl -nae 'system(qw(git branch -d), $F[0]) if $F[3] eq q{gone]}'; \
}; f"

Avec cela, un simple git pruneitgood nettoiera les branches locales et distantes qui ne sont plus nécessaires après la fusion.

2
Ken Williams

Sur la base des réponses ci-dessus, j'utilise cette doublure plus courte:

git remote Prune Origin | grep pruned | awk 'BEGIN{FS="/"} ; { print $2 }' | xargs git branch -d
1
hidralisk

La variante de Schleis ne fonctionne pas pour moi (Ubuntu 12.04), alors permettez-moi de vous proposer mes variantes (claires et brillantes :):

Variante 1 (je préférerais cette option):

git for-each-ref --format='%(refname:short) %(upstream)' refs/heads/ | awk '$2 !~/^refs\/remotes/' | xargs git branch -D 

Variante 2:

une. Séchage à sec:

comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | awk '{print "git branch -D " $1}'

b. Supprimer les branches:

comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | xargs git branch -D
1
daniilyar

J'ai transformé la réponse acceptée en un script robuste. Vous le trouverez dans mon dépôt git-extensions .

$ git-Prune --help
Remove old local branches that do not exist in <remote> any more.
With --test, only print which local branches would be deleted.
Usage: git-Prune [-t|--test|-f|--force] <remote>
1
Ingo Karkat

Il ne semble pas y avoir de solution simple, mais de trop nombreux cas Edge (comme une branche ayant "maître" dans son nom, etc.) Le plus sûr est ces étapes: 

  1. git branch -vv | grep 'gone]' > stale_branches.txt 
  2. affichez le fichier et supprimez les lignes des branches que vous souhaitez conserver (comme branche principale!); vous n'avez pas besoin de modifier le contenu d'une ligne
  3. awk '{print $1}' stale_branches.txt | xargs git branch -d
1
Oliver

Essayez ceci dans git bash, pour chercher et élaguer les références aux branches supprimées, puis élaguez les branches locales qui suivaient celles qui avaient été supprimées:

git fetch -p && git branch -d `git branch -vv | grep ': gone]' | awk '{print $1}' | xargs`

N'oubliez pas de vérifier d'abord une branche qui ne sera pas supprimée, afin de ne pas bloquer la suppression de la branche.

1

J'ai atteint cette page en cherchant la réponse "comment puis-je supprimer les branches extraites localement qui n'ont plus de branche en amont"

Je ne me souciais pas non plus de savoir si la branche locale avait déjà été fusionnée, car la canalisation dans git branch -d avertira simplement au lieu de supprimer les branches locales non fusionnées.

git branch -a | grep Origin | tr -s ' ' | cut -d '/' -f3 | egrep -v -f /dev/fd/0 <(git branch -a | grep -v Origin) | grep branch_prefix_that_I_care_about | xargs git branch -d

# translation
# git branch -a | grep Origin | tr -s ' ' | cut -d '/' -f3
## this finds all remote branch names minus the "remote/Origin/" part
#
# <(git branch -a | grep -v Origin)
## this finds all local branch names and redirects it into the previous command
#
# egrep -v -f /dev/fd/0 STUFF
## this is doing some weird magic that I'm grokking as "take the set difference from whatever was piped in"
#
#
# overall translation: (STUFF TO CONSIDER) | egrep magic <(STUFF TO REMOVE FROM CONSIDERATION) | do cool things with resulting stuff
0
Meredith