1862 votes

Supprimer le suivi des branches qui ne sont plus sur la télécommande

Existe-t-il un moyen simple de supprimer toutes les branches de suivi dont l'équivalent distant n'existe plus ?

Exemple :

Branches (locales et distantes)

  • maître
  • origine/maître
  • origine/bug-fix-a
  • origine/bug-fix-b
  • origine/bug-fix-c

Localement, je n'ai qu'une branche master. Maintenant, je dois travailler sur Correction de bogues - alors je le vérifie, je travaille dessus et j'envoie les changements à la télécommande. Ensuite, je fais la même chose avec bug-fix-b .

Branches (locales et distantes)

  • maître
  • Correction de bogues -
  • bug-fix-b
  • origine/maître
  • origine/bug-fix-a
  • origine/bug-fix-b
  • origine/bug-fix-c

Maintenant, j'ai des succursales locales maître , Correction de bogues - , bug-fix-b . Le responsable de la branche Master va fusionner mes modifications dans maître et supprimer toutes les branches qu'il a déjà fusionnées.

L'état actuel est donc maintenant :

Branches (locales et distantes)

  • maître
  • Correction de bogues -
  • bug-fix-b
  • origine/maître
  • origine/bug-fix-c

Maintenant je voudrais appeler une commande pour supprimer les branches (dans ce cas-ci Correction de bogues - , bug-fix-b ), qui ne sont plus représentés dans le référentiel distant.

Ce serait quelque chose comme la commande existante git remote prune origin mais plutôt git local prune origin .

25 votes

Question très bien formulée avec un exemple très clair. Excellent travail !

3 votes

Pourquoi la majorité des réponses répondent : "Supprimer les branches qui ont été fusionnées", alors que la question porte spécifiquement sur les "branches qui ne sont plus sur la télécommande". C'est une différence assez importante.

1886voto

aubreypwd Points 124

git remote prune origin élague les branches de suivi qui ne sont pas sur la télécommande.

git branch --merged liste les branches qui ont été fusionnées dans la branche courante.

xargs git branch -d supprime les branches listées sur l'entrée standard.

Soyez prudent en supprimant les branches listées par git branch --merged . La liste pourrait comprendre master ou d'autres branches que vous préférez ne pas supprimer.

Pour vous donner la possibilité de modifier la liste avant de supprimer des branches, vous pourriez faire ce qui suit en une seule ligne :

git branch --merged >/tmp/merged-branches && \
  vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches

1064voto

jason.rickman Points 968

La façon la plus sûre de le faire est d'utiliser la commande "plomberie". git for-each-ref avec la variable d'interpolation %(upstream:track) qui sera [gone] lorsque la branche n'est plus sur le distant :

git fetch -p && for branch in $(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}'); do git branch -D $branch; done

Cette approche est un peu plus sûre que l'utilisation de la commande "porcelain", car il n'y a pas de risque de correspondance accidentelle sur une partie du message de commit. Voici une version utilisant les commandes git "porcelain" :

git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done

La façon dont cela fonctionne est qu'après la commande

git fetch -p

supprime les références distantes, lorsque vous exécutez

git branch -vv

il affichera "parti" comme état de la télécommande. Par exemple,

$ git branch -vv
  master                 b900de9 [origin/master: behind 4] Fixed bug
  release/v3.8           fdd2f4e [origin/release/v3.8: behind 2] Fixed bug
  release/v3.9           0d680d0 [origin/release/v3.9: behind 2] Updated comments
  bug/1234               57379e4 [origin/bug/1234: gone] Fixed bug

C'est ce sur quoi les scripts itèrent.

445voto

dlsso Points 2843

La plupart de ces réponses ne répondent pas réellement à la question initiale. J'ai fait un tas de recherches et ce était la solution la plus propre que j'ai trouvée. Voici une version légèrement plus approfondie de cette réponse :

  1. Vérifiez votre branche par défaut. Habituellement git checkout master
  2. Ejecutar 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 les branches locales qui montrent qu'elles sont "parties" en git branch -vv .

Notes :

Si votre langue n'est pas l'anglais, vous devrez modifier les paramètres suivants gone au mot approprié. Les branches qui sont uniquement locales ne seront pas touchées. Les branches qui ont été supprimées à distance mais qui n'ont pas été fusionnées afficheront une notification mais ne seront pas supprimées en local. Si vous voulez les supprimer également, changez -d à -D .

364voto

Andrew Spencer Points 1870

Normalement, je ne répondrais pas à 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 est la suivante : "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, sans être fragile, sans être 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 : toutes reposent sur l'analyse de la sortie de Git par des commandes de manipulation de texte ou des langages de script, qui ne sont pas nécessairement présents sur tous les systèmes. En plus de cela, la plupart des suggestions utilisent des commandes de 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 ; script devraient utiliser les commandes de "plomberie" de niveau inférieur).

Pour en savoir plus :


Si vous voulez faire cela en toute sécurité, pour le cas d'utilisation de la question (garbage-collect tracking des branches qui ont été supprimées sur le serveur mais qui existent toujours en tant que branches locales) et avec des commandes Git de haut niveau uniquement, vous devez

  • git fetch --prune (ou git fetch -p qui est un alias, ou git prune remote origin qui fait la même chose sans récupérer les données, et qui n'est probablement pas ce que vous voulez la plupart du temps).
  • Notez toutes les branches distantes qui sont signalées comme supprimées. Ou, pour les retrouver plus tard, git branch -v (toute branche de suivi orpheline sera marquée "[gone]").
  • git branch -d [branch_name] sur chaque branche de suivi orpheline

(c'est ce que proposent certaines des autres réponses).

Si vous voulez script une solution, alors for-each-ref 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 comment l'exploiter sans écrire une boucle shell script, ou utiliser xargs ou autre.


Explication du contexte

Pour comprendre ce qui se passe, vous devez comprendre que, dans la situation de suivi des branches, vous n'avez pas une branche, mais trois. (Et rappelez-vous que "branche" signifie simplement un pointeur vers un commit).

Étant donné une branche de suivi feature/X le référentiel distant (serveur) aura cette branche et l'appellera feature/X . Votre dépôt local possède une branche remotes/origin/feature/X ce qui signifie, "C'est ce que le dépôt distant m'a dit que sa branche feature/X était, la dernière fois que nous avons parlé," et enfin, le dépôt local a une branche feature/X qui pointe vers votre dernier commit, et est configuré pour "suivre" remotes/origin/feature/X Ce qui signifie que vous pouvez tirer et pousser pour les maintenir alignés.

A 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 local feature/X (que vous ne voulez probablement plus, puisque le travail sur la fonctionnalité X est vraisemblablement terminé), et vos remotes/origin/feature/X qui 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 redondances. remotes/origin/feature/X -- c'est ce que git fetch --prune mais pour une raison inconnue, il ne vous permet pas de supprimer automatiquement vos propres feature/X ... même si votre feature/X contient toujours les informations de suivi orphelines, il dispose donc des informations nécessaires pour identifier les anciennes branches de suivi qui ont été entièrement fusionnées. (Après tout, il peut donner vous les informations qui vous permettent d'effectuer vous-même l'opération à la main).

88voto

chris31389 Points 15

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 principale

git remote update origin --prune les branches éloignées des prunes

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

Select-String -Pattern ": gone]" ne récupère que les enregistrements qui ont été retirés de la liste des enregistrements à distance.

% { $_.toString().Trim().Split(" ")[0]} obtenir le nom de la branche

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X