Supprimer les branches de suivi qui ne sont plus à distance

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

exemple:

Branches (locales et éloignées)

  • maître
  • origine / master
  • origine/bug-fix-un
  • origine/bug-fix-b
  • origine/bug-fix-c

localement, je n'ai qu'un maître direction. Maintenant je dois travailler sur bug-fix-a , donc je vérifie, travaille dessus, et pousse les changements à la télécommande. Ensuite, je fais la même chose avec bug-fix-b .

Branches (locales et éloignées)

  • maître
  • bug-fix-un
  • bug-fix-b
  • origine / master
  • origine/bug-fix-un
  • origine / bug-fix-b
  • origine/bug-fix-c

Maintenant, j'ai des branches locales maître , bug-fix-un , 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:

Branches (locales et éloignées)

  • maître
  • bug-fix-un
  • bug-fix-b
  • origine / master
  • origine/bug-fix-c

Maintenant, je voudrais appeler une commande pour supprimer des branches (dans ce cas bug-fix-un , bug-fix-b ), qui ne sont plus représentés dans le dépôt distant.

ce serait quelque chose comme la commande existante git remote prune origin , mais plus comme git local prune origin .

616
demandé sur Andrew Spencer 2011-10-11 17:37:35
la source

25 ответов

git remote prune origin pruneaux suivi branches pas sur la télécommande.

git branch --merged liste les succursales qui ont été fusionnées dans la succursale actuelle.

xargs git branch -d supprime les branches énumérées à l'entrée standard.

attention à supprimer les branches énumérées par git branch --merged . La liste peut inclure master ou d'autres branches que vous préférez ne pas supprimer.

pour vous donner l'occasion d'éditer le liste avant de supprimer des branches, vous pouvez faire ce qui suit sur une ligne:

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

694
répondu aubreypwd 2016-12-14 01:02:21
la source

après la commande

git fetch -p

supprime les références à distance, lorsque vous exécutez

git branch -vv

il affichera "gone" comme statut à distance. 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

donc vous pouvez écrire un script simple pour supprimer les branches locales qui ont disparu télécommandes:

git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print }'`; do git branch -D $branch; done
311
répondu jason.rickman 2017-08-21 13:45:22
la source

la plupart de ces réponses ne répondent pas à la question initiale. J'ai fait un tas de fouilles et ce était la solution la plus propre que j'ai trouvé. Voici une version un peu plus complète de cette réponse:

  1. Vérifiez votre branche par défaut. Habituellement git checkout master
  2. Exécuter git fetch -p && git branch -vv | awk '/: gone]/{print }' | xargs git branch -d

explication:

oeuvres de tailler vos branches de pistage puis supprimer les branches locales qui montrent qu'elles sont "parties" dans git branch -vv .

Notes:

si votre langue est différente de l'anglais, vous devez remplacer gone par le mot approprié. Les Branches locales ne seront pas touchés. 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 sur local. Si vous voulez supprimer celles-ci et remplacer -d par -D .

191
répondu dlsso 2018-01-20 18:02:28
la source

semble la solution est ici - https://stackoverflow.com/a/1072178/133986

En bref, git remote prune la magie

53
répondu Mailo 2017-05-23 15:34:45
la source

j'ai trouvé la réponse ici: Comment puis-je supprimer toutes les branches git qui ont été fusionnées?

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

assurez-vous que nous tenons maître

vous pouvez vous assurer que master , ou toute autre branche d'ailleurs, ne soit pas supprimé en ajoutant un autre grep après le premier. Dans ce cas, vous iriez:

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

Donc, si nous voulions garder master , develop et staging par exemple, nous irions:

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

en faire un alias

comme il est un peu long, vous pourriez vouloir ajouter un alias à votre .zshrc ou .bashrc . Le mien est appelé gbpurge (pour git branches purge ):

alias gbpurge='git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d'

puis rechargez votre .bashrc ou .zshrc :

. ~/.bashrc

ou

. ~/.zshrc
42
répondu karlingen 2017-05-23 14:55:00
la source

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 dont l'équivalent à distance n'existe plus?"

si "simple" signifie pas fragile, pas dangereux, et sans recours à des outils que tous les lecteurs n'auront pas, alors la bonne réponse est: non.

Certaines réponses sont simples, mais ils ne font pas ce qui était demandé. D'autres font ce qui a été demandé, mais ne sont pas simples: tous s'appuient sur l'analyse de la sortie Git (et de la sortie en porcelaine pour démarrer dans la plupart des cas) au moyen de commandes de manipulation de texte ou de langages de script, qui peuvent ne pas être présents sur tous les systèmes.

autre lecture: https://stackoverflow.com/a/20107184/587365 et https://stackoverflow.com/a/26152574/587365

Si vous voulez faire cela en toute sécurité, pour le cas d'utilisation dans la question (garbage-collect tracking branches qui ont été supprimés sur le serveur, mais existent toujours en tant que branches locales) et avec des commandes Git de haut niveau seulement, 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 chercher, et n'est probablement pas ce que vous voulez la plupart du temps).
  • noter toutes les branches distantes qui sont déclarées comme supprimées. Ou, pour les retrouver plus tard, git branch -v (toute branche orpheline de tracking sera marquée "[gone]").
  • git branch -d [branch_name] sur chaque orphelin de suivi de la branche

explication de Fond

pour comprendre ce qui se passe, vous devez comprendre que, dans la situation de suivre les branches, vous n'avez pas une branche, mais trois. (Et garder à l'esprit qu'une "branche" est une étiquette pour un pointeur vers un commit.)

Pour une branche feature/X , le dépôt distant aura cette branche et de l'appeler feature/X . Votre dépôt local a une branche remotes/origin/feature/X qui signifie, "C'est ce que le serveur 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 dernière propagation, et est configuré pour "suivre" remotes/origin/feature/X , ce qui signifie que vous pouvez tirer et pousser pour garder les trois alignés.

à un moment donné, quelqu'un a supprimé le feature/X sur le serveur. A partir de ce moment, il vous reste votre feature/X local (que vous ne voulez probablement plus, puisque le travail sur la fonctionnalité X est probablement terminé), et votre remotes/origin/feature/X qui est certainement inutile parce que son seul but était de se souvenir de l'état de la branche du serveur.

et Git vous permettra de nettoyer automatiquement le redondant remotes/origin/feature/X -- c'est ce que fait le git fetch --prune -- mais pour une raison quelconque, il ne vous permet pas de supprimer automatiquement votre propre feature/X ... même si votre feature/X contient toujours l'information de suivi orphelin, il a donc l'information pour identifier les anciennes directions générales de suivi qui ont été entièrement fusionnées. (Après tout, ça peut donner vous l'information qui vous permet de faire l'opération en main vous-même.)

36
répondu Andrew Spencer 2018-10-02 13:29:40
la source

supprimer toutes les branches qui ont été fusionnées dans le maître, mais n'essayez pas de supprimer le maître lui-même:

git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)

ou ajouter 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 checkout master branch

git pull origin master s'assurer que la branche locale a tous les changements à distance fusionnés

git fetch -p supprimer les références à branches distantes qui ont été supprimées

git branch -d $(git branch master --merged | grep master -v) supprimer toutes les branches qui ont été fusionnées dans master, mais n'essayez pas de supprimer master lui-même

25
répondu cs01 2017-09-21 00:58:16
la source
git fetch -p

cela supprimera toutes les branches qui ne sont pas suivies à distance.

16
répondu ckirksey3 2014-10-17 19:20:30
la source

pourrait être utile à certains, simple une ligne pour vider toutes les branches locales sauf maître et développer

git branch | grep -v "master" | grep -v "develop" | xargs git branch -D
11
répondu Francois 2018-02-28 14:27:49
la source

je ne pense pas qu'il y est une commande intégrée pour ce faire, mais il est sûr de faire ce qui suit:

git checkout master
git branch -d bug-fix-a

lorsque vous utilisez -d , git refusera de supprimer la branche à moins qu'elle ne soit complètement fusionnée avec HEAD ou sa branche de suivi à distance en amont. Donc, vous pouvez toujours en boucle sur la sortie de git 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 pas bug-fix-d soit supprimé juste parce que origin/bug-fix-d contient son histoire. Au lieu de cela, vous pouvez créer un script quelque chose comme le suivant:

#!/bin/sh

git checkout master &&
for r in $(git for-each-ref refs/heads --format='%(refname:short)')
do
  if [ x$(git merge-base master "$r") = x$(git rev-parse --verify "$r") ]
  then
    if [ "$r" != "master" ]
    then
      git branch -d "$r"
    fi
  fi
done

avertissement: je n'ai pas testé ce script - utilisez seulement avec soin...

10
répondu Mark Longair 2014-02-07 17:45:29
la source

cela supprimera toutes les ramifications locales fusionnées sauf la référence principale locale et celle actuellement utilisée:

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

et cela supprimera toutes les branches qui ont déjà été retirées du dépôt à distance référencé par " ", mais qui sont encore disponibles localement dans " " remotes/origin ".

git remote prune origin
10
répondu pabloa98 2017-02-27 22:53:24
la source

Windows Solution

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 commute sur la branche master

git remote update origin --prune pruneaux branches éloignées

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

Select-String -Pattern ": gone]" obtient seulement le les enregistrements où ils ont été retirés de remote.

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

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

8
répondu chris31389 2018-06-26 13:56:47
la source

le modèle correspondant à "parti" dans la plupart des autres solutions était un peu effrayant pour moi. Pour être plus sûr, cela utilise le drapeau --format pour retirer l'état de suivi en amont de chaque branche.

j'avais besoin d'une version Windows, donc cela supprime toutes les branches qui sont listées comme "parties" en utilisant Powershell:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | 
    ? { $_ -ne "" } | 
    % { git branch -D $_ }

la première ligne indique le nom des succursales locales dont la succursale en amont est"disparue". La ligne suivante supprime les lignes vides (qui sont des sorties pour les branches qui ne sont pas "parties"), alors le nom de la branche est passé à la commande pour supprimer la branche.

8
répondu Patrick Quirk 2018-09-21 17:18:25
la source

basé sur l'information ci-dessus, cela a fonctionné pour moi:

git br -d `git br -vv | grep ': gone] ' | awk '{print }' | xargs`

il supprime toutes les branches locales avec sont ': gone] ' sur la télécommande.

5
répondu Joost den Boer 2016-12-28 12:40:27
la source

encore-une autre-réponse pour la pile, en tirant fortement de https://stackoverflow.com/a/48411554/2858703 (ce que j'aime parce qu'il semble supprimer toute ambiguïté sur l'endroit où gone] correspond dans la sortie git branch ) mais en ajoutant un * nix bent:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" \
  | sed 's,^refs/heads/,,;/^$/d' \
  | xargs git branch -D

j'ai ceci enveloppé dans un script git-gone sur mon chemin:

#!/usr/bin/env bash

action() {
  ${DELETE} && xargs git branch -D || cat
}

get_gone() {
  git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" \
    | sed 's,^refs/heads/,,;/^$/d'

}

main() {
  DELETE=false
  while [ $# -gt 0 ] ; do
    case "" in
      (-[dD] | --delete) DELETE=true ;;
    esac
    shift
  done
  get_gone | action
}

main "${@}"

NB-l'option -- format semble être assez nouvelle; j'avais besoin de mise à niveau git à partir de 2.10.quelque chose à 2.16.3 pour l'obtenir.

4
répondu bxm 2018-03-28 15:09:38
la source
grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -d

la commande ci-dessus peut être utilisée pour récupérer les branches qui sont fusionnées et supprimées dans remote et elle supprime la branche locale qui n'est plus disponible dans remote

3
répondu thiruclassic 2018-08-17 09:09:45
la source

rien de tout cela n'était vraiment bon pour moi. 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'ont jamais été configurées pour suivre une branche distante (i.e.: mes branches dev locales). En outre, je voulais un simple one-liner qui utilise juste 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 rendre cette commande simple.

c'est finalement Ce qui a fini dans mon ~/.gitconfig :

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

Voici une commande git config --global ... pour ajouter facilement git prune-branches :

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

NOTE: dans la commande config, j'utilise l'option -d pour git branch plutôt que -D , comme je le fais dans ma configuration actuelle. J'utilise -D parce que je ne veux pas entendre Git se plaindre de branches non fusionnées. Vous pouvez également vouloir cette fonctionnalité. Si c'est le cas, utilisez simplement -D au lieu de -d à la fin de cette commande de configuration.

2
répondu Karl Wilbur 2018-09-14 15:17:31
la source

j'ai inventé ce script bash. Il garde toujours les branches develop , qa , master .

git-clear() {
  git pull -a > /dev/null

  local branches=$(git branch --merged | grep -v 'develop' | grep -v 'master' | grep -v 'qa' | sed 's/^\s*//')
  branches=(${branches//;/ })

  if [ -z $branches ]; then
    echo 'No branches to delete...'
    return;
  fi

  echo $branches

  echo 'Do you want to delete these merged branches? (y/n)'
  read yn
  case $yn in
      [^Yy]* ) return;;
  esac

  echo 'Deleting...'

  git remote prune origin
  echo $branches | xargs git branch -d
  git branch -vv
}
1
répondu BrunoLM 2017-01-17 14:16:37
la source

cela a fonctionné pour moi:

git branch -r | awk '{print }' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print }' | xargs git branch -d
1
répondu Fareed Alnamrouti 2018-02-19 08:11:05
la source

Je ne suis pas sûr pour combien de temps, mais j'utilise git-up maintenant, qui prend soin de cela.

je ne git up et il commence à suivre des branches nouvelles et supprime les anciens.

juste pour être clair, il n'est pas hors-des-boîtes git commande - https://github.com/aanand/git-up

BTW il cache aussi l'arbre sale et fait rebases encore avec juste git up .

J'espère que ce sera utile pour quelqu'un

0
répondu Mailo 2015-08-25 01:14:02
la source

Voici une solution que j'utilise pour la coquille du poisson. Testé sur Mac OS X 10.11.5 , fish 2.3.0 et git 2.8.3 .

function git_clean_branches
  set base_branch develop

  # work from our base branch
  git checkout $base_branch

  # remove local tracking branches where the remote branch is gone
  git fetch -p

  # find all local branches that have been merged into the base branch
  # and delete any without a corresponding remote branch
  set local
  for f in (git branch --merged $base_branch | grep -v "\(master\|$base_branch\|\*\)" | awk '/\s*\w*\s*/ {print }')
    set local $local $f
  end

  set remote
  for f in (git branch -r | xargs basename)
    set remote $remote $f
  end

  for f in $local
    echo $remote | grep --quiet "\s$f\s"
    if [ $status -gt 0 ]
      git branch -d $f
    end
  end
end

quelques notes:

assurez-vous de régler le bon base_branch . Dans ce cas, j'utilise develop comme branche de base, mais ça pourrait être n'importe quoi.

Cette partie est très importante: grep -v "\(master\|$base_branch\|\*\)" . Il garantit que vous ne supprimez pas master ou votre branche de base.

J'utilise git branch -d <branch> comme précaution supplémentaire, afin de ne pas supprimer toute branche qui n'a pas été complètement fusionnée avec la tête amont ou courante.

Un moyen facile de tester est de remplacer git branch -d $f avec echo "will delete $f" .

je suppose que je devrais aussi ajouter: utiliser à vos propres risques!

0
répondu lps 2016-07-01 00:22:29
la source

j'utilise une méthode courte pour faire le tour, je vous recommande de faire la même chose car il pourrait sauver quelques heures et vous donner plus de visibilité

il suffit d'ajouter l'extrait suivant dans votre .bashrc (.bashprofile sur macos).

git-cleaner() { git fetch --all --prune && git branch --merged | grep -v -E "\bmaster|preprod|dmz\b" | xargs -n 1 git branch -d ;};
  1. récupération de toutes les télécommandes de
  2. obtenir seulement les branches fusionnées de git
  3. Supprimer de cette liste les branches "protégées / importantes
  4. supprimer le reste (E. g, clean and merged branches)

vous devrez éditer le grep regex afin de l'adapter à vos besoins (Ici, il empêche master, preprod et dmz de supprimer)

0
répondu Ben Cassinat 2017-12-07 17:33:38
la source

Basé sur Git Astuce: Supprimer les Anciennes Branches Locales , qui ressemble à jason.solution de rickman j'ai mis en œuvre une commande personnalisée à cet effet appelé git gone en utilisant Bash:

$ git gone
usage: git gone [-pndD] [<branch>=origin]
OPTIONS
  -p  prune remote branch
  -n  dry run: list the gone branches
  -d  delete the gone branches
  -D  delete the gone branches forcefully

EXAMPLES
git gone -pn    prune and dry run
git gone -d     delete the gone branches

git gone -pn regroupe la taille et la liste des branches "disparues":

$ git gone -pn
  bport/fix-server-broadcast         b472d5d2b [origin/bport/fix-server-broadcast: gone] Bump modules
  fport/rangepos                     45c857d15 [origin/fport/rangepos: gone] Bump modules

ensuite, vous pouvez appuyer sur la gâchette en utilisant git gone -d ou git gone -D .

Notes

  • l'expression régulière que j'ai utilisée est "$BRANCH/.*: gone]"$BRANCH serait normalement origin . Cela ne fonctionnera probablement pas si votre sortie Git est localisée en français, etc.
  • Sebastian Wiesner a également porté à la rouille pour les utilisateurs de Windows. Celui-ci est aussi appelé git gone .
0
répondu Eugene Yokota 2018-09-27 21:14:01
la source

j'utilise cette méthode pour avoir plus de contrôle.

git branch -D $(git branch | grep -v "master" | grep -v "develop")

c'est supprimer toutes les branches non nommées: master ou develop .

-2
répondu Corey C 2017-09-13 21:14:30
la source

cela va supprimer toutes les branches distantes qui ne sont pas présentes localement (en ruby):

bs = `git branch`.split; bs2 = `git branch -r | grep origin`.split.reject { |b| bs.include?(b.split('/')[1..-1].join('/')) }; bs2.each { |b| puts `git  push origin --delete #{b.split('/')[1..-1].join('/')}` }

expliquée:

# local branches
bs = `git branch`.split
# remote branches
bs2 = `git branch -r | grep origin`.split
# reject the branches that are present locally (removes origin/ in front)
bs2.reject! { |b| bs.include?(b.split('/')[1..-1].join('/')) }
# deletes the branches (removes origin/ in front)
bs2.each { |b| puts `git  push origin --delete #{b.split('/')[1..-1].join('/')}` }
-3
répondu Dorian 2016-12-07 21:48:14
la source

Autres questions sur git git-branch