Nous utilisons des tags dans git dans le cadre de notre processus de déploiement. De temps en temps, nous souhaitons nettoyer ces balises en les supprimant de notre référentiel distant.
C'est assez simple. Un utilisateur supprime la balise locale et la balise distante en un seul jeu de commandes. Nous avons un petit script Shell qui combine les deux étapes.
Le 2ème (3ème, 4ème, ...) utilisateur a maintenant des balises locales qui ne sont plus reflétées sur la télécommande.
Je recherche une commande similaire à git remote Prune Origin
qui nettoie localement les branches de suivi pour lesquelles la branche distante a été supprimée.
Alternativement, une simple commande de liste des balises distantes pourrait être utilisée pour comparer les balises locales renvoyées via git tag -l
.
Bonne question. :) Je n'ai pas de réponse complète ...
Cela dit, vous pouvez obtenir une liste de balises distantes via git ls-remote
. Pour répertorier les balises dans le référentiel référencé par Origin
, vous devez exécuter:
git ls-remote --tags Origin
Cela renvoie une liste de hachages et de noms de balises conviviales, tels que:
94bf6de8315d9a7b22385e86e1f5add9183bcb3c refs/tags/v0.1.3
cc047da6604bdd9a0e5ecbba3375ba6f09eed09d refs/tags/v0.1.4
...
2f2e45bedf67dedb8d1dc0d02612345ee5c893f2 refs/tags/v0.5.4
Vous pouvez certainement créer un script bash pour comparer les tags générés par cette liste avec ceux que vous avez localement. Jetez un coup d'œil à git show-ref --tags
, qui génère les noms de balises sous la même forme que git ls-remote
).
En passant, git show-ref
a une option qui fait le contraire de ce que vous souhaitez. La commande suivante listerait toutes les balises de la branche distante que vous avez ne pas localement:
git ls-remote --tags Origin | git show-ref --tags --exclude-existing
C'est une excellente question, je me demandais la même chose.
Je ne voulais pas écrire un script, alors j'ai cherché une solution différente. La clé est de découvrir que vous pouvez supprimer une balise localement, puis utilisez git fetch pour "la récupérer" depuis le serveur distant. Si le tag n'existe pas sur la télécommande, il restera supprimé.
Ainsi, vous devez taper deux lignes dans l'ordre:
git tag -l | xargs git tag -d
git fetch --tags
Celles-ci:
Supprimer toutes les balises du référentiel local. FWIW, xargs place chaque balise générée par "balise -l" sur la ligne de commande pour "balise -d". Sans cela, git ne supprimera rien car il ne lit pas stdin (idiot).
Récupère toutes les balises actives du référentiel distant.
Cela fonctionne même un régal sous Windows.
De Git v1.7.8 à v1.8.5.6, vous pouvez utiliser ceci:
git fetch <remote> --Prune --tags
Cela ne fonctionne pas sur les versions plus récentes de git (à partir de v1.9.0) à cause du commit e66ef7ae6f31f2 . Je ne veux pas vraiment le supprimer car cela a fonctionné pour certaines personnes.
Comme suggéré par "Chad Juliano", avec toutes les versions de Git depuis la version 1.7.8, vous pouvez utiliser la commande suivante:
git fetch --Prune <remote> +refs/tags/*:refs/tags/*
Vous devrez peut-être entourer la partie balises de guillemets (sous Windows par exemple) pour éviter une expansion par caractère générique:
git fetch --Prune <remote> "+refs/tags/*:refs/tags/*"
Si vous ne voulez que les tags qui existent sur la télécommande, supprimez simplement tous vos tags locaux:
$ git tag -d $(git tag)
Et puis récupérez tous les tags distants:
$ git fetch --tags
Toutes les versions de Git depuis la v1.7.8 comprennent git fetch
avec un refspec, alors que depuis la v1.9.0, l'option --tags
annule l'option --Prune
. Pour une solution générale, essayez ceci:
$ git --version
git version 2.1.3
$ git fetch --Prune Origin "+refs/tags/*:refs/tags/*"
From ssh://xxx
x [deleted] (none) -> rel_test
Pour plus d'informations sur la façon dont le comportement "--tags" avec "--Prune" a changé dans Git v1.9.0, voir: https://github.com/git/git/commit/e66ef7ae6f31f246dead62f574cc2acb75fd001c
On dirait que les versions récentes de Git (je suis sur git v2.20) permettent de dire simplement
git fetch --Prune --Prune-tags
Beaucoup plus propre!
https://git-scm.com/docs/git-fetch#_pruning
Vous pouvez également configurer git pour toujours supprimer les tags lors de la récupération:
git config fetch.pruneTags true
Si vous souhaitez uniquement supprimer les balises lors de la récupération d'une télécommande spécifique, vous pouvez utiliser l'option remote.<remote>.pruneTags
. Par exemple, pour toujours supprimer les balises lors de l'extraction de Origin mais pas d'autres télécommandes,
git config remote.Origin.pruneTags true
Git supporte nativement le nettoyage des tags locaux:
git fetch --tags --Prune
Cette commande extrait les dernières balises et supprime toutes les balises supprimées.
Montrer la différence entre les balises locales et distantes:
diff <(git tag | sort) <( git ls-remote --tags Origin | cut -f2 | grep -v '\^' | sed 's#refs/tags/##' | sort)
git tag
donne la liste des tags locauxgit ls-remote --tags
donne la liste des chemins complets vers les tags distantscut -f2 | grep -v '\^' | sed 's#refs/tags/##'
analyse uniquement le nom de la liste dans la liste des chemins de balise distantsLes lignes commençant par "<" sont vos balises locales qui ne figurent plus dans le référentiel distant. S'ils sont peu nombreux, vous pouvez les supprimer manuellement un par un. S'ils sont nombreux, vous effectuez plus de recherches et de canalisations pour l'automatiser.
Vient d'ajouter une commande git sync-local-tags à pivotal_git_scripts Gem fork sur GitHub:
https://github.com/kigster/git_scripts
Installez la gemme, puis exécutez "git sync-local-tags" dans votre référentiel pour supprimer les balises locales qui n'existent pas sur la télécommande.
Sinon, vous pouvez simplement installer ce script ci-dessous et l'appeler "git-sync-local-tags":
#!/usr/bin/env Ruby
# Delete tags from the local Git repository, which are not found on
# a remote Origin
#
# Usage: git sync-local-tags [-n]
# if -n is passed, just print the tag to be deleted, but do not
# actually delete it.
#
# Author: Konstantin Gredeskoul (http://tektastic.com)
#
#######################################################################
class TagSynchronizer
def self.local_tags
`git show-ref --tags | awk '{print $2}'`.split(/\n/)
end
def self.remote_tags
`git ls-remote --tags Origin | awk '{print $2}'`.split(/\n/)
end
def self.orphaned_tags
self.local_tags - self.remote_tags
end
def self.remove_unused_tags(print_only = false)
self.orphaned_tags.each do |ref|
tag = ref.gsub /refs\/tags\//, ''
puts "deleting local tag #{tag}"
`git tag -d #{tag}` unless print_only
end
end
end
unless File.exists?(".git")
puts "This doesn't look like a git repository."
exit 1
end
print_only = ARGV.include?("-n")
TagSynchronizer.remove_unused_tags(print_only)
TortoiseGit peut comparer les tags maintenant.
Le journal de gauche est sur la télécommande, la droite est au niveau local.
Utilisation de la fonctionnalité Comparer les balises de la boîte de dialogue Synchroniser:
Voir aussi TortoiseGit numéro 297
La même réponse que @Richard W mais pour Windows (PowerShell)
git tag | foreach-object -process { git tag -d $_ }
git fetch -t
Que diriez-vous de cela: supprimez toutes les balises locales et effectuez une nouvelle extraction? Considérant que votre repo peut contenir des sous-modules:
git submodule foreach --recursive 'git tag | xargs git tag -d'
(alternatively, "for i in `find .git -type d -name '*tags*'`; do rm -f $i/*; done")
git fetch -t
git submodule foreach --recursive git fetch -t