Je suis un processus de développement dans lequel je crée une nouvelle branche locale pour chaque nouvelle fonctionnalité ou carte d’histoire. Une fois terminé, je fusionne la branche en maître, puis en Push.
Ce qui a tendance à se produire avec le temps en raison d’une combinaison de paresse et d’oubli, c’est que je me retrouve avec une longue liste de succursales locales, dont certaines (comme les pics) peuvent ne pas avoir été fusionnées.
Je sais comment répertorier toutes mes branches locales et comment supprimer une seule branche, mais je me demandais s'il existait une commande git qui me permet de supprimer toutes mes branches locales?
Vous trouverez ci-dessous le résultat de la commande git branch --merged
.
user@machine:~/projects/application[master]$ git branch --merged
STORY-123-Short-Description
STORY-456-Another-Description
STORY-789-Blah-Blah
* master
Toutes les tentatives de suppression des branches listées avec grep -v \*
(selon les réponses ci-dessous) génèrent des erreurs:
error: branch 'STORY-123-Short-Description' not found.
error: branch 'STORY-456-Another-Description' not found.
error: branch 'STORY-789-Blah-Blah' not found.
J'utilise:
git 1.7.4.1
Ubuntu 10.04
GNU bash, version 4.1.5 (1) - release
GNU grep 2.5.4
Juste une note, je passerais à git 1.7.10. Vous obtiendrez peut-être ici des réponses qui ne fonctionneront pas avec votre version. Mon hypothèse est qu'il faudrait préfixer le nom de la branche avec refs/heads/
.
ATTENTION, ne procédez comme suit que si vous avez copié votre dossier de travail et votre répertoire .git.
Parfois, je ne fais que supprimer les branches que je ne veux pas directement de .git/refs/heads
. Toutes ces branches sont des fichiers texte contenant les 40 caractères sha-1 du commit sur lequel ils pointent. Vous aurez des informations superflues dans votre .git/config
si vous avez configuré un suivi spécifique pour l'un d'entre eux. Vous pouvez également supprimer ces entrées manuellement.
La sous-commande 'git branch -d' peut supprimer plusieurs branches. Donc, simplifiant la réponse de @ sblom mais en ajoutant un xargs critique:
git branch -D `git branch --merged | grep -v \* | xargs`
ou encore simplifié pour:
git branch --merged | grep -v \* | xargs git branch -D
Il est important de noter que, comme l'a noté @AndrewC, l'utilisation de git branch
pour les scripts est déconseillée. Pour l'éviter, utilisez quelque chose comme:
git for-each-ref --format '%(refname:short)' refs/heads | grep -v master | xargs git branch -D
Attention justifiée lors des suppressions!
$ mkdir br
$ cd br; git init
Initialized empty Git repository in /Users/ebg/test/br/.git/
$ touch README; git add README; git commit -m 'First commit'
[master (root-commit) 1d738b5] First commit
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README
$ git branch Story-123-a
$ git branch Story-123-b
$ git branch Story-123-c
$ git branch --merged
Story-123-a
Story-123-b
Story-123-c
* master
$ git branch --merged | grep -v \* | xargs
Story-123-a Story-123-b Story-123-c
$ git branch --merged | grep -v \* | xargs git branch -D
Deleted branch Story-123-a (was 1d738b5).
Deleted branch Story-123-b (was 1d738b5).
Deleted branch Story-123-c (was 1d738b5).
J'ai trouvé un moyen plus agréable dans un commentaire sur ce problème sur github :
git branch --merged master --no-color | grep -v master | grep -v stable | xargs git branch -d
edit: a ajouté l'option sans couleur et en excluant les branches stables (ajoutez d'autres branches selon vos besoins)
L'analyse de la sortie de git branch
n'est pas recommandée et ne constitue pas une bonne réponse pour les futurs lecteurs de Stack Overflow.
git branch
est ce qu'on appelle une commande de porcelaine. Les commandes de porcelaine ne sont pas conçues pour être analysées par la machine et la sortie peut changer entre les différentes versions de Git. git
branch
de manière à rendre l'analyse difficile (par exemple, la colorisation). Si un utilisateur a défini color.branch
, vous obtiendrez des codes de contrôle dans la sortie. Cela conduira à error: branch 'foo' not found.
si vous essayez de le canaliser vers une autre commande. Vous pouvez éviter cela avec l'indicateur --no-color
à git branch
, mais qui sait quelles autres configurations utilisateur pourraient briser des choses.git branch
peut faire d'autres choses qui sont ennuyeuses à analyser, comme mettre un astérisque à côté de la branche actuellement extraiteLe mainteneur de git a ceci à dire à propos des scripts autour de la sortie de git branch
Pour savoir ce qu’est la branche actuelle, les utilisateurs occasionnels/négligents peuvent avoir scripté autour de la branche git, ce qui est faux. Nous décourageons activement contre l'utilisation de toute commande de porcelaine, y compris la branche git, dans scripts, car la sortie de la commande est sujette à changer en aider cas d'utilisation de la consommation humaine.
Les réponses qui suggèrent de modifier manuellement les fichiers dans le répertoire .git
(comme .git/refs/heads) sont également problématiques (les références peuvent être à la place en .git/metallic-refs, ou Git peut changer leur disposition interne à l'avenir).
Git fournit la commande for-each-ref
pour récupérer une liste de branches.
Git 2.7.X introduira l’option --merged
afin que vous puissiez faire quelque chose comme ci-dessous pour trouver et supprimer toutes les branches fusionnées dans HEAD
for mergedBranch in $(git for-each-ref --format '%(refname:short)' --merged HEAD refs/heads/)
do
git branch -d ${mergedBranch}
done
À partir de Git 2.6.X, vous devrez répertorier toutes les branches locales, puis les tester individuellement pour voir si elles ont été fusionnées (ce qui sera beaucoup plus lent et légèrement plus compliqué).
for branch in $(git for-each-ref --format '%(refname:short)' refs/heads/)
do
git merge-base --is-ancestor ${branch} HEAD && git branch -d ${branch}
done
Pour supprimer toutes les branches sauf celle que vous avez empruntée:
for b in `git branch --merged | grep -v \*`; do git branch -D $b; done
Je recommanderais de remplacer git branch -D $b
par un echo $b
les premières fois afin de vous assurer qu'il supprime les branches souhaitées.
La manière la plus simple de supprimer toutes les branches, mais de garder les autres comme "develop" et "master" est la suivante:
git branch | grep -v "develop" | grep -v "master" | xargs git branch -D
très utile !
J'ai trouvé plus facile d'utiliser simplement l'éditeur de texte et Shell.
git checkout <TAB>
dans le shell. Montrera toutes les branches locales.git branch -D <PASTE THE BRANCHES NAMES HERE>
.C'est tout.
La commande ci-dessous supprimera toutes les branches locales à l'exception de la branche principale.
git branch | grep -v "master" | xargs git branch -D
La commande ci-dessus
J'ai eu un genre de situation similaire et récemment trouvé la commande suivante utile.
git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep>/) printf "%s", $0 }'`
Si vous voulez conserver plusieurs branches, alors
git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep1>|<Branch_You_Want_to_Keep2>/) printf "%s", $0 }'`
espérons que cela aide quelqu'un.
Si vous n'avez pas besoin de passer par Git lui-même, vous pouvez également supprimer les en-têtes sous .git/refs/heads manuellement ou par programme. Ce qui suit devrait fonctionner avec un minimum de peaufinage sous Bash:
shopt -s extglob
rm -rf .git/refs/heads/!(master)
Cela supprimera toutes les branches locales à l'exception de votre branche principale. Puisque vos branches en amont sont stockées sous .git/refs/remotes , elles resteront intactes.
Si vous n'utilisez pas Bash, ou voulez rediffuser un grand nombre de référentiels Git à la fois, vous pouvez faire quelque chose de similaire avec GNU trouver:
find . \
-path remotes -path logs -Prune -o \
-wholename \*.git/refs/heads/\* \! -name master -print0 |
xargs -0 rm -rf
La solution de recherche est probablement plus portable, mais les chemins d’élagage et les noms de fichiers sont délicats et potentiellement plus sujets aux erreurs.
Pour supprimer toutes les branches locales de Linux sauf celui sur lequel vous vous trouvez
// hard delete
git branch -D $(git branch)
Aucune des réponses ne satisfaisait pleinement mes besoins, alors allons-y:
git branch --merged | grep -E "(feature|bugfix|hotfix)/" | xargs git branch -D && git remote Prune Origin
Cela supprimera toutes les branches locales qui sont fusionnées et qui commencent par feature/
, bugfix/
ou hotfix/
. Ensuite, la Origin
distante amont est supprimée (vous devrez peut-être entrer un mot de passe).
Fonctionne sur Git 1.9.5.
Basé sur une combinaison de plusieurs réponses ici - si vous voulez conservez toutes les branches qui existent à distance mais supprimez le reste , la solution suivante fera l'affaire:
git for-each-ref --format '%(refname:short)' refs/heads | grep -Ev `git ls-remote --quiet --heads Origin | awk '{print substr($2, 12)}'| paste -sd "|" -` | xargs git branch -D
A partir de la ligne de commande Windows, supprimez tout sauf la branche extraite actuelle en utilisant:
for /f "tokens=*" %f in ('git branch ^| find /v "*"') do git branch -D %f
Les réponses ci-dessus fonctionnent bien. Voici une autre approche lorsque nous avons beaucoup de succursales dans le dépôt local et que nous devons supprimer beaucoup de succursales, sauf quelques-unes qui se trouvent dans la machine locale.
Le premier git branch
listera toutes les branches locales.
Pour transposer la colonne de noms de branches en une seule ligne de fichier en exécutant une commande unix
git branch > sample.txt
Ceci sera sauvegardé dans sample.txt fichier . Et lancera awk 'BEGIN { ORS = " " } { print }' sample.txt
commande dans Shell. Cela transformera la colonne en ligne et copiera la liste des noms de branches sur une seule ligne.
Et puis courir git branch -D branch_name(s)
.
Ceci supprimera toutes les branches listées présentes dans
La manière la plus pragmatique: assurez-vous de ne pas avoir de travail non engagé sur master
, commit/Push si nécessaire, clonez une nouvelle copie du référentiel et supprimez l'ancien.
J'ai écrit un script Shell afin de supprimer toutes les branches locales sauf develop
branches=$(git branch | tr -d " *")
output=""
for branch in $branches
do
if [[ $branch != "develop" ]]; then
output="$output $branch"
fi
done
git branch -d $output
Le script suivant supprime les branches. Utilisez-le et modifiez-le à vos risques et périls, etc. etc.
Sur la base des autres réponses à cette question, j'ai fini par écrire un script rapide pour moi-même. Je l'ai appelé "gitbd" (git branch -D) mais si vous l'utilisez, vous pouvez le renommer comme vous le souhaitez.
gitbd() {
if [ $# -le 1 ]
then
local branches_to_delete=`git for-each-ref --format '%(refname:short)' refs/heads/ | grep "$1"`
printf "Matching branches:\n\n$branches_to_delete\n\nDelete? [Y/n] "
read -n 1 -r # Immediately continue after getting 1 keypress
echo # Move to a new line
if [[ ! $REPLY == 'N' && ! $REPLY == 'n' ]]
then
echo $branches_to_delete | xargs git branch -D
fi
else
echo "This command takes one arg (match pattern) or no args (match all)"
fi
}
Elle proposera de supprimer toutes les branches qui correspondent à un argument de modèle, si elles sont passées, ou toutes les branches locales si elles sont appelées sans argument. Cela vous donnera également une étape de confirmation, puisque, vous savez, nous supprimons des éléments, c’est bien Nice.
C'est un peu bête - s'il n'y a pas de branches qui correspondent au modèle, il ne s'en rend pas compte.
Un exemple de sortie:
$ gitbd test
Matching branches:
dummy+test1
dummy+test2
dummy+test3
Delete? [Y/n]
Pour Powershell, cela fonctionnera:
git branch --format '%(refname:lstrip=2)' --merged `
| Where-Object { $_ -ne 'master' } `
| ForEach-Object { git branch -d $_ }
Assurez-vous de le faire en premier
git fetch
Une fois que vous avez toutes les informations sur les branches distantes, utilisez la commande suivante pour supprimer toutes les branches sauf master
git branch -a | grep -v "master" | grep remotes | sed 's/remotes\/Origin\///g' | xargs git Push Origin --delete
Bien que ce ne soit pas une solution en ligne de commande, je suis surpris que l'interface graphique Git n'ait pas encore été suggérée.
J'utilise la ligne de commande 99% du temps, mais dans ce cas, il est trop lent (d'où la question initiale) ou vous ne savez pas ce que vous êtes sur le point de supprimer lorsque vous aurez recours à une manipulation de Shell longue et astucieuse.
L'interface utilisateur résout ce problème, car vous pouvez rapidement cocher les branches que vous souhaitez supprimer et être rappelé à celles que vous souhaitez conserver, sans avoir à taper une commande pour chaque branche.
Dans l'interface utilisateur, accédez à Branche -> Supprimer et à Ctrl + Clic les branches que vous souhaitez supprimer pour les mettre en surbrillance. Si vous voulez vous assurer qu'ils sont fusionnés dans une branche (telle que dev
), sous Supprimer uniquement si fusionné dans, définissez Local Branch sur dev
. Sinon, réglez-le sur Toujours pour ignorer cette vérification.