Problème: je veux un moyen de supprimer toutes les branches locales que j'ai qui n’ont pas de télécommande. Il est assez facile de canaliser les noms des branches dans un git branch -D {branch_name}
, mais comment puis-je obtenir cette liste en premier lieu?
Par exemple:
Je crée une nouvelle branche sans télécommande:
$ git co -b no_upstream
Je liste toutes mes branches, il n'y en a qu'une avec une télécommande
$ git branch -a
master
* no_upstream
remotes/Origin/HEAD -> Origin/master
remotes/Origin/master
Quelle commande puis-je exécuter pour obtenir no_upstream
comme réponse?
Je peux exécuter git rev-parse --abbrev-ref --symbolic-full-name @{u}
et cela montrera qu'il n'a pas de télécommande:
$ git rev-parse --abbrev-ref --symbolic-full-name @{u}
error: No upstream configured for branch 'no_upstream'
error: No upstream configured for branch 'no_upstream'
fatal: ambiguous argument '@{u}': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
Mais comme il s’agit d’une erreur, cela ne me permettra pas de l’utiliser ni de le diriger vers d’autres commandes. J'ai l'intention de l'utiliser comme un script Shell alias'd de git-delete-unbranched
ou peut-être créer un bijou très simple comme git-branch-delete-orphans
Toute aide serait appréciée! Merci
J'ai récemment découvert git branch -vv
qui est la version "très détaillée" de la commande git branch
.
Il génère les branches avec les branches distantes si elles existent, au format suivant:
25-timeout-error-with-many-targets 206a5fa WIP: batch insert
31-target-suggestions f5bdce6 [Origin/31-target-suggestions] Create target suggestion for team and list on save
* 54-feedback-link b98e97c [Origin/54-feedback-link] WIP: Feedback link in mail
65-digest-double-publish 2de4150 WIP: publishing-state
Une fois que vous avez cette sortie joliment formatée, il vous suffit simplement de la glisser dans cut
et awk
pour obtenir votre liste:
git branch -vv | cut -c 3- | awk '$3 !~/\[/ { print $1 }'
Résultats dans la sortie suivante:
25-timeout-error-with-many-targets
65-digest-double-publish
La partie cut
normalise simplement les données en supprimant les deux premiers caractères (y compris *
) de la sortie avant de les transmettre à awk
.
La partie awk
imprime la première colonne s'il n'y a pas de crochet entre la troisième colonne.
Bonus: créer un alias
Facilitez l’exécution en créant un alias dans votre fichier global .gitconfig
(ou ailleurs):
[alias]
local-branches = !git branch -vv | cut -c 3- | awk '$3 !~/\\[/ { print $1 }'
Important: La barre oblique inverse doit être échappée dans l'alias sinon vous aurez un fichier gitconfig non valide.
Bonus: Filtrage à distance
Si, pour une raison quelconque, vous disposez de plusieurs télécommandes de suivi pour différentes branches, il est assez facile de spécifier la télécommande sur laquelle vous souhaitez effectuer le contrôle. Il suffit d'ajouter le nom de la télécommande au modèle awk. Dans mon cas, c'est Origin
pour que je puisse faire ceci:
git branch -vv | cut -c 3- | awk '$3 !~/\[Origin/ { print $1 }'
git branch
(sans aucune option) répertorie uniquement les branches locales, mais vous ne savez pas si elles suivent ou non une branche distante.
Habituellement, ces branches locales devraient être supprimées une fois fusionnées dans master
(comme indiqué dans ce numéro de git-sweep ):
git branch --merged master | grep -v master | xargs git branch -d
Ce n'est pas aussi complet que vous voulez, mais c'est un début.
Avec
--merged
, seules les branches fusionnées dans la validation nommée (c’est-à-dire les branches dont les validations des astuces sont accessibles à partir de la validation nommée) seront répertoriées.
Édition tardive: mieux c'est
git for-each-ref --format='%(refname:short) %(upstream)' refs/heads \
| awk '$2 !~/^refs\/remotes/'
sur GNU/n'importe quoi
for b in `git branch|sed s,..,,`; do
git config --get branch.$b.remote|sed Q1 && echo git branch -D $b
done
S'il y avait probablement plus d'une poignée de branches, il y aurait de meilleures façons, en utilisant comm -23
sur la sortie de git branch|sed|sort
et git config -l|sed|sort
.
J'ai un problème similaire. Je veux supprimer toutes les branches locales qui suivaient les branches distantes qui sont maintenant supprimées. Je trouve que git remote Prune Origin
était insuffisant pour supprimer les branches que je voulais disparaître. Une fois la télécommande supprimée, je veux que le local s’éloigne aussi. Voici ce qui a fonctionné pour moi:
De mon ~/.gitconfig
:
[alias]
Prune-branches = !git remote Prune Origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -d
EDIT: Comme demandé, voici une commande git config --global ...
pour l’ajouter facilement en tant que git Prune-branches
:
git config --global alias.Prune-branches '!git remote Prune Origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'
NOTE: J'ai changé le -d
en -D
dans ma configuration réelle car je ne veux pas entendre Git se plaindre des branches non fusionnées. Vous pouvez voulez aussi cette fonctionnalité. Si c'est le cas, utilisez simplement -D
au lieu de -d
à la fin de cette commande.
En outre, FWIW, votre fichier de configuration global serait presque toujours ~/.gitconfig
.
EDIT: (Correctif OSX) Tel qu'écrit, cela ne fonctionne pas sous OSX à cause de l'utilisation de xargs -r
(merci, Korny ).
Le -r
permet d'empêcher xargs
d'exécuter git branch -d
sans nom de branche, ce qui entraînera un message d'erreur "fatal: branch name required
". Si le message d'erreur ne vous dérange pas, vous pouvez simplement supprimer l'argument -r
en xargs
et le tour est joué.
Cependant, si vous ne voulez pas voir un message d'erreur (et qui peut vraiment vous en vouloir), vous aurez besoin de quelque chose d'autre qui vérifie si un tuyau est vide. Si vous pouvez utiliser ifne de moreutils . Vous devez insérer ifne
avant xargs
, ce qui empêchera xargs
de s'exécuter avec des données vides. NOTE: ifne
considère que rien n'est pas vide, cela inclut les lignes vides, vous pouvez donc toujours voir ce message d'erreur. Je n'ai pas testé cela sur OSX.
Voici cette ligne git config
avec ifne
:
git config --global alias.Prune-branches '!git remote Prune Origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | ifne xargs git branch -d'
Cela fonctionne pour moi:
git branch -vv | grep -v Origin
(Si votre télécommande porte un nom autre que Origin, remplacez-le).
Ceci listera toutes les branches qui ne suivent pas une télécommande, ce qui ressemble à ce que vous recherchez.
Mise en oeuvre de powershell brute: (si Origin est votre seule télécommande)
@($branches = git br -r; git branch | %{ echo $_ | sed 's/..//' }) `
| %{ if (($branches | ss "Origin/$_") -eq $null) { `
echo "git branch -D $_" `
} `
}
Voici quelque chose que j'ai utilisé dans PowerShell avec des commentaires pour expliquer son travail. Pour tenter de clarifier ce qui se passe, je n'ai utilisé aucune commande PS abrégée. N'hésitez pas à le compresser au niveau de cryptage souhaité :)
$verboseList = @(git br -vv)
foreach ($line in $verboseList)
{
#get the branch name
$branch = [regex]::Match($line, "\s(\S+)\s").Captures.Groups[1].Value
#check if the line contains text to indicate if the remote is deleted
$remoteGone = $line.Contains(": gone]")
#check if the line does not contain text to indicate it is a tracking branch (i.e., it's local)
$isLocal = !($line.Contains("[Origin/"))
if ($remoteGone -or $isLocal)
{
#print the branch name
$branch
}
}
Je sinthetize ma propre commande git pour obtenir les branches Origin/***: gone
:
git remote Prune Origin && git branch -vv | cut -c 3- | grep ': gone]' | awk '{print $1}' | xargs -n1 -r echo git branch -d
git remote Prune Origin && git branch -vv
imprimera les branches en mode prolixe
cut -c 3-
enlèvera les tout premiers caractères
grep ': gone]'
imprimera uniquement les branches gone remote
awk '{print $1}'
imprimera le nom de la succursale
xargs -n1 -r echo git branch -d
imprimera la commande git branch -d
pour supprimer les branches (-n1 gérera une commande par heure, -r pour éviter d'émettre une commande si aucune branche n'est présente)
ASTUCE: supprimer la commande "echo" pour exécuter les commandes au lieu de n'imprimer que, j'ai laissé cela dans la commande pour vérifier les commandes avant d'envoyer à git.
CONSEIL 2: émettez git branch -D
si et seulement si vous êtes sûr de vouloir supprimer les branches non fusionnées