Supprimer les branches Git locales après les avoir supprimées sur le référentiel distant


162

Je souhaite que mes référentiels locaux et distants soient toujours synchronisés en termes de branches.

Après un examen de Pull Request sur GitHub, je fusionne et supprime ma branche là-bas (à distance). Comment pourrais-je récupérer ces informations dans mon référentiel local et demander à Git de supprimer également ma version locale de la branche?


Voulez-vous supprimer vos succursales de suivi à distance, vos succursales locales ou les deux? Vous pouvez en fait écrire un alias (bash ou git) qui prendra toutes les branches distantes supprimées et trouver des copies locales à supprimer également, le tout dans une seule commande.

Essayez peut-être d'utiliser les commandes suivantes pour trouver quelque chose, git ls-remoteet git show-ref.

En outre, vous voudrez peut-être vérifier git symbolic-refet git update-ref.

merci pour votre aide, j'ai fini par trouver la réponse ailleurs. Voir ma réponse.
sf89

Réponses:


180

Le moyen rapide

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

NB: si vous n'êtes pas sur master, cela a le potentiel de supprimer la branche. Continuez à lire pour la «meilleure façon».

Assurez-vous que nous gardons le maître

Vous pouvez vous assurer que master, ou toute autre branche d'ailleurs, ne sera pas supprimée en grepdemandant plus. 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, developet stagingpar exemple, nous irions:

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

Faites-en un alias

Comme il est un peu long, vous voudrez peut-être ajouter un alias à votre fichier .zshrcou .bashrc. Le mien est appelé gbpurge(pour git branches purge):

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

Puis rechargez votre .bashrcou .zshrc:

. ~/.bashrc

ou

. ~/.zshrc

Vous pouvez mettre les commandes dans un alias et en faire une seule commande. Cependant, comme il branchs'agit d'une porcelaine et non d'une commande de plomberie , faites attention aux changements d'interface utilisateur dans les futures versions de Git qui pourraient le casser.

1
Parfait! Notez qu'à la suite du workflow Github, la branche locale mastersera supprimée.
Rubens Mariuzzo

Non, je suis sûr qu'il reste là (je l'utilise tous les jours et cela ne semble pas le faire).
sf89

4
Pour info, si vous souhaitez conserver plusieurs branches, vous pouvez utiliser un seul grep, comme ceci: grep -Ev '(\*|master|important-branch)'
Andrew Burns

4
Si vous voulez le mettre dans votre à la ~/.gitconfigplace, ajoutez ce qui suit à la [alias]section: gbpurge = !"git branch --merged | grep -Ev '\\*|master|develop|staging' | xargs -n 1 git branch -d"(pas besoin d'utiliser () dans l'expression grep).
dskrvk

82

J'utilise le même flux avec GitHub, et je n'ai pas trouvé les réponses précédentes satisfaisantes, car les git branch --mergedbranches ont été fusionnées, mais toutes n'ont pas été supprimées à distance dans mon cas. Donc, cela a fonctionné pour moi:

git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d

où:

  • git fetch --all -p: mettre à jour le statut des succursales locales
  • git branch -vv: lister le statut des succursales locales
  • grep ": gone]": filtrer les supprimés
  • awk '{ print $1 }': extraire leurs noms
  • xargs -n 1 git branch -d: passez le nom à la commande de suppression

Remarque: si vous préférez, vous pouvez utiliser -D au lieu de -d, qui impose la suppression.

Par exemple:

someUsr@someHost:~/repo$ git branch -a
basic-testing
integration-for-tests
* master
origin
playground-for-tests
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

someUsr@someHost:~/repo$ git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d
Fetching origin
Deleted branch integration-for-tests (was fbc609a).
Deleted branch playground-for-tests (was 584b900).

someUsr@someHost:~/repo$ git branch -a
basic-testing
* master
origin
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

Référence:

http://git-scm.com/book/en/v2/Git-Branching-Remote-Branches


3
J'ai pris la liberté de m'assurer que je ferai toujours ça contre le maître, donc: git checkout master; git pull origin master; git fetch --all -p; git branch -vv | grep gone | awk '{ print $1 }' | xargs -n 1 git branch -d Super script et explication, merci pour ça :)
Miguelgraz

Notez que branch -vvmontre le dernier message de validation de la branche. Si vous aviez "disparu" dans ce message, grep gonecela toucherait également cette branche. Donc, grep ": gone]"est probablement un peu plus sûr à utiliser.
chawkinsuf

1
C'est la vraie réponse à la question. Je vous remercie.
Andrei Gladkyi

1
Encore mieux:awk '$3 $4 ~ /:gone]$/ { print $1 }'
Jakub Bochenski

3
En plus d'avoir besoin -Dau lieu de -dcela, c'est la réponse parfaite!
Cas du

72

essayer:

git pull --prune

qui supprime votre branche locale, si sa branche distante correspondante est supprimée.

Actualisé:

La déclaration ci-dessus n'est pas correcte.

En fait, la course git pull --prunesera seulement enlever les branches de suivi à distance tels que

télécommandes / origine / fff
télécommandes / origine / dev
télécommandes / origine / maître

Ensuite, vous pouvez exécuter git branch -rpour vérifier les branches de suivi à distance laissées sur votre machine. Supposons que les branches de gauche soient:

origine / dev
origine / maître

ce qui signifie que la branche origin/fffest supprimée.

Donc, après avoir couru git pull --prune, exécutez simplement:

git branch --merged | grep -vFf <(git branch -r | cut -d'/' -f2-)

vous pouvez découvrir toutes les succursales locales qui:

  1. n'ont plus de succursales distantes correspondantes;
  2. peut être retiré en toute sécurité.

puis, <the command above> | xargs git branch -dpeut tous les supprimer.


42
Cette réponse n'est pas tout à fait correcte. L' --pruneindicateur supprimera uniquement les branches de suivi à distance, pas les branches locales.

3
D'accord avec @Cupcake ici, cela n'atteint pas ce que je recherche ici.
sf89

6
Je ne vais pas voter pour, mais c'est ce dont j'avais besoin après avoir supprimé les branches locales, puis supprimé de GitHub, mais elles existent toujours en tant que télécommandes dans ma commande git remote -v.
Spechal

8
Vous pouvez aussi le faire git fetch --prune, c'est ma façon de choisir
e_m0ney

1
Une autre erreur Git provenant d'un avis trouvé sur le débordement de la pile ... a git pull --pruneentraîné "Vous avez demandé à extraire de la télécommande '--prune', mais vous n'avez pas spécifié de branche. Comme il ne s'agit pas de la télécommande configurée par défaut pour votre branche actuelle, vous doit spécifier une branche sur la ligne de commande. "
jww

23

Cela devrait fonctionner pour éviter de supprimer les branches maître et de développement avec la solution acceptée:

git branch --merged | egrep -v "^\*|master|development" | xargs -n 1 git branch -d

16

Pour les personnes utilisant PowerShell, c'est l'équivalent de la réponse ci - dessus :

git branch -vv | Select-String -Pattern ': gone]' | ForEach-Object{($_ -split "\s+")[1]} | %{ git branch -D $_ }
  1. Filtrer toutes les branches marquées comme disparues
  2. Appelez git branch -Dchacune des branches trouvées

6

Rien de tout cela ne fonctionnait pour moi. Vous pouvez voir mon autre réponse ici: https://stackoverflow.com/a/34969726/550454

Mais essentiellement, j'ai maintenant ceci dans mon ~/.gitconfig:

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

5

Solution très simple: supprimez votre dépôt local et clonez à nouveau le dépôt distant. Cela peut ne pas sembler très élégant, mais c'est simple et vous comprendrez exactement ce que vous faites sans lire les pages de manuel :-).


1
Pourquoi tant de votes négatifs? Je veux dire évidemment pas efficace, surtout avec des dépôts plus importants, mais il fait ce qu'OP a demandé. Y a-t-il une autre raison de ne pas faire cela?
3ocène le

6
Parce que vous perdrez toutes vos branches locales, vos cachettes, vos commits non poussés ... c'est comme pêcher avec de la dynamite.
sevenseacat

1
La même chose se produit lorsque l'ordinateur portable sur lequel vous travaillez est corrompu, perdu ou volé, donc j'ai tendance à ne rien garder de crucial localement. Il me semble préférable de simplement créer une branche et de la pousser, même pour les petites fonctionnalités, et de la supprimer après qu'elle ne soit plus utile.

1

J'ai écrit ce one-liner pour lister toutes les branches locales qui n'ont pas de branche distante correspondante:

diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -

Une fois cela fait, la suppression de ces branches locales est facile avec xargs:

diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -|xargs -r git branch -d

cela me liste masteraussi, cela ne fonctionne pas comme prévu; soyez prudent
Enrico

1

Je fais juste cela pour supprimer les branches locales fusionnées:

git branch -d $(git branch --merged)

et si vous souhaitez également supprimer les suivis inexistants:

git pull --prune

1

Dans le cas où vous venez de pousser et de fusionner votre branche vers master, procédez comme suit dans git bash:

git branch -d branch_name_to_delete

Si vous êtes actuellement dans cette branche, cela vous repoussera en maître. À ce stade, tirez avec

git pull

-2

La réponse votée a le potentiel de supprimer le maître. Considérez l'exemple pratique ci-dessous.

J'avais deux branches de fonctionnalités hemen_README et hemen_BASEBOX qui ont été fusionnées dans develop, puis develop a été fusionnée dans master. Les branches de fonctionnalité hemen_README et hemen_BASEBOX ont été supprimées à distance mais étaient toujours affichées localement. Aussi je ne suis pas sur le maître localement, mais sur le développement.

Dans ce cas

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
    * develop                      671ad6c Merged in hemen_README (pull request #1)
        hemen_BASEBOX                a535c0f added global exec paths to puppet manifest
        hemen_README                 ba87489 Updated Readme with considerable details
        master                       8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
        remotes/origin/develop       671ad6c Merged in hemen_README (pull request #1)
        remotes/origin/hemen_BASEBOX a535c0f added global exec paths to puppet manifest
        remotes/origin/hemen_README  ba87489 Updated Readme with considerable details
        remotes/origin/master        2f093ce Merged in develop (pull request #3)

Donc, si j'exécute la commande partielle ci-dessus

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch --merged | grep -v "\*"
        hemen_BASEBOX
        hemen_README
        master

Notez qu'il affiche également le maître, qui sera finalement supprimé.

En tout cas j'ai pu le faire. Je partage mon journal de session avec vous sur la façon dont j'ai réalisé cela.

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git remote prune origin --dry-run
    Pruning origin
    URL: git@bitbucket.org:hemenkapadiapublic/vagrant-webdev.git
     * [would prune] origin/hemen_BASEBOX
     * [would prune] origin/hemen_README
    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git remote prune origin 
    Pruning origin
    URL: git@bitbucket.org:hemenkapadiapublic/vagrant-webdev.git
     * [pruned] origin/hemen_BASEBOX
     * [pruned] origin/hemen_README

Je viens de vérifier quel sera élagué puis élagué. en regardant la commande de branche ci-dessous, nous nous sommes occupés des télécommandes

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
    * develop                671ad6c Merged in hemen_README (pull request #1)
        hemen_BASEBOX          a535c0f added global exec paths to puppet manifest
        hemen_README           ba87489 Updated Readme with considerable details
        master                 8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
        remotes/origin/develop 671ad6c Merged in hemen_README (pull request #1)
        remotes/origin/master  2f093ce Merged in develop (pull request #3)

Maintenant, allez-y et supprimez les succursales locales

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -d hemen_BASEBOX 
    Deleted branch hemen_BASEBOX (was a535c0f).
    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -d hemen_README
    Deleted branch hemen_README (was ba87489).

Bon maintenant les branches sont à souhait.

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
    * develop                671ad6c Merged in hemen_README (pull request #1)
        master                 8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
        remotes/origin/develop 671ad6c Merged in hemen_README (pull request #1)
        remotes/origin/master  2f093ce Merged in develop (pull request #3)

Bien sûr, il a le potentiel de supprimer le maître. Veuillez lire attentivement la question. Comme je l'ai dit là-bas, j'avais besoin d'un moyen de nettoyer les choses dans ma section locale. Cela signifie supprimer toutes les branches qui n'existent plus à distance. Si le maître n'est plus là, il disparaîtra également sur votre machine locale.
sf89
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.