Comment éliminer les twigs de suivi locales qui n’existent plus sur la télécommande

Avec git remote prune origin je peux supprimer les twigs locales qui ne sont plus sur la télécommande.

Mais je veux aussi supprimer les twigs locales créées à partir de ces twigs distantes (une vérification si elles sont non fusionnées serait bien).

Comment puis-je faire ceci?

Après l’élagage, vous pouvez obtenir la liste des twigs distantes avec git branch -r . La liste des twigs avec leur twig de suivi à distance peut être récupérée avec git branch -vv . Ainsi, en utilisant ces deux listes, vous pouvez trouver les twigs 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 un shell Bourne 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 récupère la liste des twigs distantes et la transmet à egrep via l'entrée standard. Et filtre les twigs qui ont une twig de suivi à distance (en utilisant git branch -vv et en filtrant pour celles d' origin ), puis en obtenant la première colonne de cette sortie qui sera le nom de la twig. Enfin, passez tous les noms de twig dans la commande delete branch.

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

Rappelez-vous également que vous devez d'abord lancer git fetch --prune , sinon git branch -r verra toujours les twigs distantes.

Si vous souhaitez supprimer toutes les twigs locales déjà fusionnées dans master, vous pouvez utiliser la commande suivante:

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

Plus d’infos

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

  -p, --prune After fetching, remove any remote-tracking twigs 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 3 ans après le fait, voici un peu plus d’informations sur la raison pour laquelle j’ai présenté cette réponse …

Tout d’abord, l’OP dit vouloir “supprimer également les twigs locales créées à partir de ces twigs distantes [qui ne sont plus sur la télécommande]”. Ce n’est pas sans ambiguïté possible dans git . Voici un exemple.

Disons que j’ai un repo sur un serveur central et qu’il a deux twigs, appelées A et B Si je clone ce repository dans mon système local, mon clone aura des refs locales (pas encore des twigs 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  

Les faits pertinents ici sont que, pour une raison quelconque, j’ai choisi de créer une twig sur mon repo local qui a un nom différent de son origine, et j’ai également une twig locale qui n’existe pas (encore) sur le repo d’origine.

Maintenant, disons que je supprime les deux twigs A et B du repo distant et que je mets à jour mon repo local ( git fetch de certaines formes), ce qui fait disparaître mes refs origin/A et origin/B locales. Maintenant, mon repo local a toujours trois twigs, A , Z et C Aucun d’entre eux n’a une twig correspondante sur le repo distant. Deux d’entre eux étaient “créés à partir de … twigs distantes”, mais même si je savais qu’il y avait une twig appelée B sur l’origine, je n’ai aucun moyen de savoir que Z été créé à partir de B , car il a été renommé en le processus, probablement pour une bonne raison. Donc, en réalité, sans certains processus externes d’enregistrement des métadonnées d’origine de twig, ou un humain qui connaît l’historique, il est impossible de déterminer laquelle des trois twigs, le cas échéant, l’OP cible pour la suppression. Sans certaines informations externes que git ne conserve pas automatiquement pour vous, git fetch -p est à peu près aussi proche que possible, et toute méthode automatique pour tenter littéralement ce que l’OP demandé risque de supprimer trop de twigs ou de manquer certaines que l’OP voudrait sinon supprimer.

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

Cela supprimera les twigs locales pour lesquelles les twigs de suivi à distance ont été élaguées. (Assurez-vous que vous êtes sur la twig master !)

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

Détails:

  • git branch -vv affiche “gone” pour les twigs locales que 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 indépendamment)

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

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

 git config --global fetch.prune true 

Lorsque vous appelez git fetch ou git pull , les références aux twigs distantes supprimées sont automatiquement supprimées.

Il y a un paquet NPM soigné qui le fait pour vous (et cela devrait fonctionner sur plusieurs plates-formes).

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

Et puis git removed-twigs va vous montrer toutes les twigs locales obsolètes, et git removed-twigs --prune pour les supprimer.

Plus d’infos ici.

Il listera les twigs locales dont la twig de suivi à distance est supprimée de la télécommande

 $ git remote prune origin --dry-run 

Si vous voulez dé-référencer ces twigs locales de local qui ne sont pas suivies

 $ git remote prune origin 

Si vous utilisez Windows et Powershell, vous pouvez utiliser les éléments suivants pour supprimer toutes les twigs locales ayant été fusionnées dans la twig actuellement extraite:

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

Explication

  • Liste la twig actuelle et les twigs qui ont été fusionnées
  • Filtre la twig en cours
  • Nettoie les espaces de git ou de fin de la sortie git pour chaque nom de twig restant
  • Supprime les twigs locales fusionnées

Cela vaut la peine de git branch --merged d’abord pour s’assurer que cela ne va supprimer que ce à quoi vous vous attendez.

(Porté / automatisé à partir de http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-twigs-in-local-and-remote-repositories/ .)

Solution Windows

Pour Microsoft Windows Powershell:

git checkout master; git remote update origin --prune; git branch -vv | Select-Ssortingng -Pattern ": gone]" | % { $_.toSsortingng().Split(" ")[0]} | % {git branch -d $_}

Explication

git checkout master passe à la twig maître

git remote update origin --prune prune twigs distantes

git branch -vv obtient une sortie verbeuse de toutes les twigs ( référence git )

Select-Ssortingng -Pattern ": gone]" n’obtient que les enregistrements où ils ont été supprimés de la télécommande.

% { $_.toSsortingng().Split(" ")[0]} récupère le nom de la twig

% {git branch -d $_} supprime la twig

Je ne sais pas comment faire tout à la fois, mais git git branch -d supprimera une twig locale SEULEMENT si elle est complètement fusionnée. Notez le minuscule d.

git branch -D (notez le D majuscule) supprimera une twig locale quel que soit son statut fusionné.

Je voulais quelque chose qui purgerait toutes les twigs locales qui suivaient une twig distante, à l’ origin , où la twig distante a été supprimée. Je n’ai pas voulu supprimer les twigs locales qui n’ont jamais été configurées pour suivre une twig distante (par exemple, mes twigs de développement locales). De plus, je voulais un simple traceur simple qui utilise uniquement 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 faire cette commande simple, puis je l’ai ajoutée en tant ~/.gitconfig dans mon ~/.gitconfig .

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

Voici une commande git config --global ... pour append facilement ceci en tant que git prune-twigs :

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

REMARQUE: L’utilisation de l’ -D pour git branch peut être très dangereuse. Donc, dans la commande de configuration 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 twigs non fusionnées, je veux juste qu’elles disparaissent. Vous souhaiterez peut-être également cette fonctionnalité. Si c’est le cas, utilisez simplement -D au lieu de -d à la fin de cette commande de configuration.

One-liner encore plus court et plus sûr:

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

Assurez-vous de vous connecter à la twig qui n’a pas encore été fusionnée avant de l’exécuter. Parce que vous ne pouvez pas supprimer la twig que vous êtes actuellement archivé

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 va nettoyer les twigs locales et distantes qui ne sont plus nécessaires après les fusions.

Sur la base des réponses ci-dessus, je suis venu 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 

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

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. Dry-run:

 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 twigs:

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

J’ai transformé la réponse acceptée en un script robuste. Vous le trouverez dans mon repository git-extensions .

 $ git-prune --help Remove old local twigs that do not exist in  any more. With --test, only print which local twigs would be deleted. Usage: git-prune [-t|--test|-f|--force]  

Voici une adaptation de la réponse de @wisbucky pour les utilisateurs de Windows:

for /f "tokens=1" %i in ('git branch -vv ^| findstr ": gone]"') DO git branch %i -d

J’utilise posh-git et malheureusement PS n’apprécie pas le nu, alors j’ai créé un script de commande ‘ol’ nommé PruneOrphanBranches.cmd:

 @ECHO OFF for /f "tokens=1" %%i in ('git branch -vv ^| findstr ": gone]"') DO CALL :ProcessBranch %%i %1 GOTO :EOF :ProcessBranch IF /I "%2%"=="-d" ( git branch %1 %2 ) ELSE ( CALL :OutputMessage %1 ) GOTO :EOF :OutputMessage ECHO Will delete branch [%1] GOTO :EOF :EOF 

Appelez-le sans paramètre pour voir une liste, puis appelez-le avec “-d” pour effectuer la suppression réelle ou “-D” pour les twigs qui ne sont pas complètement fusionnées mais que vous souhaitez supprimer de toute façon.

Essayez ceci dans git bash, pour récupérer et élaguer des références à des twigs supprimées, puis élaguer les twigs locales qui suivaient les twigs 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 twig qui ne sera pas supprimée, afin de ne pas bloquer la suppression de la twig.

Vous pouvez utiliser cette commande:

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

Git Clean: Supprimer les twigs déjà fusionnées, y compris la répartition des commandes

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

git branch --merged master | %{ if($_ -notmatch '\*.*master'){ git branch -d "$($_.Trim())" }}

Cela supprimera toutes les twigs locales qui ont été fusionnées dans master alors que vous êtes sur la twig principale .

git checkout master pour basculer.

Supprimer toute twig qui n’est pas à jour avec master

 git co master && git branch | sed s/\*/\ / | xargs git branch -d 2> /dev/null 

Si vous retirez de votre ordinateur local , voici mon moyen direct :

Allez simplement à: C:\Repo\your-project\.git\refs\heads

Chaque twig est un fichier créé sous ce dossier, supprimez simplement les fichiers correspondant à vos noms de twig

Il est difficile de trouver une méthode sur Windows, j’utilise sourcetree, et je ne veux pas supprimer un par un. Je viens de comprendre de cette façon, et cela m’a sauvé sur Windows.

Je suis à peu près sûr que git remote prune origin est ce que vous voulez.

Vous pouvez l’exécuter en tant que git remote prune origin --dry-run pour voir ce qu’il ferait sans apporter de modifications.

Utiliser l’interface graphique? Procédure manuelle, mais rapide et facile.

 $ git gui 

Sélectionnez “Branche -> Supprimer”. Vous pouvez sélectionner plusieurs twigs avec Ctrl-clic (Windows) et les supprimer toutes.