Artık uzak depoda olmayan yerel git etiketlerini kaldırın


469

Dağıtım işlemimizin bir parçası olarak git'deki etiketleri kullanıyoruz. Zaman zaman bu etiketleri uzak depomuzdan kaldırarak temizlemek istiyoruz.

Bu oldukça basit. Bir kullanıcı bir komut kümesinde yerel etiketi ve uzak etiketi siler. Her iki adımı birleştiren küçük bir kabuk betiğimiz var.

2. (3., 4., ...) kullanıcı artık uzaktan kumandaya yansıtılmayan yerel etiketlere sahip.

git remote prune originUzak dalın silindiği yerel olarak izleme dallarını temizleyen benzer bir komut arıyorum .

Alternatif olarak, üzerinden döndürülen yerel etiketlerle karşılaştırmak için uzak etiketleri listelemek için basit bir komut kullanılabilir git tag -l.


2
Budama bayat etiketlerini desteklemek için git'te
Adam Monsen

1
Not: Git 2.17 (Q2 2018) ile basit bir şey istediğinizi yapmanızı git config fetch.pruneTags truesağlayacaktır git fetch! Diğer soruya cevabımı gör .
VonC

2
Aşağıdaki yanıtlardan birinden yorum gönderme: En azından git 2.18.0 ile bu sözdizimini de kullanabilirsiniz: git fetch --prune --prune-tags origin
zutnop

Yanıtlar:


71

İyi soru. :) Tam bir cevabım yok ...

Bununla, üzerinden uzak etiketlerin bir listesini alabilirsiniz git ls-remote. Depodaki başvuruda bulunan etiketleri listelemek için şunu originçalıştırırsınız:

git ls-remote --tags origin

Bu, karma ve kolay etiket adlarının bir listesini döndürür, örneğin:

94bf6de8315d9a7b22385e86e1f5add9183bcb3c        refs/tags/v0.1.3
cc047da6604bdd9a0e5ecbba3375ba6f09eed09d        refs/tags/v0.1.4
...
2f2e45bedf67dedb8d1dc0d02612345ee5c893f2        refs/tags/v0.5.4

Bu liste tarafından oluşturulan etiketleri yerel olarak sahip olduğunuz etiketlerle karşılaştırmak için kesinlikle bir bash betiği oluşturabilirsiniz. git show-ref --tagsEtiket adlarını aynı formda üreten) bir göz atın git ls-remote.


Bir yana, git show-refistediğinizin tersini yapan bir seçenek var. Aşağıdaki komut, uzak dalda yerel olarak sahip olmadığınız tüm etiketleri listeler :

git ls-remote --tags origin | git show-ref --tags --exclude-existing

Teşekkürler Mike. Karşılaştırma için her listeyi kullanarak kendi bash betiğimi alacağım.
KEND

11
Richard W'nin cevabı, karmaşık bir senaryo ile ilgilenmiyorsanız, bunu çok daha zarif bir şekilde yapar.
Kyle Heironimus

1
Yerel olarak bulunmayan etiketlerle ilgili yan not daha fazla uzaktan kumanda kontrol etmek için genişletilebilir:git remote | xargs -L 1 git ls-remote --tags | git show-ref --tags --exclude-existing
Palec

Daha basit bir çözüm için bir sonraki cevaba bakınız
sfletche

git --prune etiketlerini destekler. Bunun hangi versiyona sokulduğundan emin değilim. git-scm.com/docs/git-fetch#git-fetch---prune-tags
John Kloian

1058

Bu harika bir soru, aynı şeyi merak ediyordum.

Farklı bir çözüm arayan bir senaryo yazmak istemedim. Anahtar, bir etiketi yerel olarak silebileceğinizi ve ardından uzak sunucudan "geri almak" için git fetch komutunu kullanabileceğinizi keşfetmektir. Etiket uzaktan kumandada yoksa, silinmiş olarak kalır.

Böylece sırayla iki satır yazmanız gerekir:

git tag -l | xargs git tag -d
git fetch --tags

Bunlar:

  1. Yerel repodaki tüm etiketleri silin. FWIW, xargs "tag -l" ile her etiket çıktısını "tag -d" komut satırına yerleştirir. Bu olmadan git hiçbir şeyi silmez çünkü stdin (aptal git) okumaz.

  2. Tüm aktif etiketleri uzak depodan getir.

Bu bile Windows üzerinde bir tedavi çalışır.


58
Bu StackOverflow benim favori git cevap olmalı. Bilgi, basitlik ve hile birleştirir ve her şeyi açıklar. Büyük
timtam

25
Ayrı bir yanıtta belirtildiği gibi, bu TÜM yerel etiketleri siler ve uzak repoda olmayanlar açıkça yeniden oluşturulmaz
ikinci

13
FWIW bu tamamen gereksiz olmalıdır. Bir git tag prune originkomut olmalı .
void.pointer

9
Bu herkes için işe yaramayabilir. Güvenli tarafta olmak için git fetch --tags yapmalısınız.
Adam Kurkiewicz

5
Bunu git tag -l | %{git tag -d $_}PowerShell'de çalıştırmak için gitmem gerekiyordu. Başkası hakkında emin değilim.
Alain

244

Git v1.7.8'den v1.8.5.6'ya kadar şunları kullanabilirsiniz:

git fetch <remote> --prune --tags

Güncelleme

Bu komut e66ef7ae6f31f2 nedeniyle git'in yeni sürümlerinde ( v1.9.0 ile başlayan) çalışmaz . Bazı insanlar için işe yaradığı için gerçekten silmek istemiyorum.

"Chad Juliano" tarafından önerildiği gibi, v1.7.8'den bu yana tüm Git sürümleriyle aşağıdaki komutu kullanabilirsiniz:

git fetch --prune <remote> +refs/tags/*:refs/tags/*

Joker karakter genişletmesini önlemek için etiketler bölümünü tırnak işaretleri içine almanız gerekebilir (örneğin Windows'ta):

git fetch --prune <remote> "+refs/tags/*:refs/tags/*"

2
Git için Windows 1.9.4-preview20140611 ile birlikte gelen belgelere başvuruyorum (ve önceki tüm sürümlerden şüpheliyim). Adı geçen belgelere "git fetch --help" ile erişirim [quote] Etiketler, yalnızca varsayılan etiket otomatik izleme veya bir --tags seçeneği nedeniyle getirildiyse budamaya tabi değildir. [/ Quote]
Félix Cantournet

2
git fetch --prune <remote> +refs/tags/*:refs/tags/*ZSH'de çalışmadı ancak BASH'de çalışıyor
Alex

3
@Alex Bunun nedeni sadece zsh'ın genişlemesi, *ancak tek bir teklifte bulunmanız iyi olur.
NSF

3
@ v01pe - şimdi bir git kısayolu var - PRUNING bölümü altındaki belgelerde açıklanan git 2.17.0'dan bu yana mevcut prune etiketleri: git-scm.com/docs/git-fetch/2.17.0 Belgeden : - -prune-tags seçeneği, uzaktan kumandanın refspec'lerinde belirtilen refs / tags / *: refs / tags / * ifadesine eşdeğerdir. Eşdeğerleri: git fetch origin --prune --prune-tagsVEYA git fetch origin --prune 'refs/tags/*:refs/tags/*'VEYA git fetch <url of origin> --prune --prune-tagsVEYAgit fetch <url of origin> --prune 'refs/tags/*:refs/tags/*'
mkisaacs

3
git fetch origin --prune --prune-tagsuzaktan izleme dallarını ve etiketleri budama. git 2.18 sürümünde kontrol edildi.
Sayı 945

158

Yalnızca uzaktan kumandada bulunan etiketleri istiyorsanız, tüm yerel etiketlerinizi silin:

$ git tag -d $(git tag)

Ve sonra tüm uzak etiketleri getir:

$ git fetch --tags

1
kusursuz, bazı etiketleri bulamayan xargs ile sorun yaşıyordum
Marcio Toshio

3
@ocroquette, bundan daha güzel olduğundan emin değilim xargs. Daha fazla etiketiniz ARG_MAXveya benzer sınırlamalarınız varsa, bu çalışmaz. Olası değil, ama mümkün ve bu yüzden xargsharika.
Paul Draper

2
"Güzel" öznel bir şeydir, herkes kendi fikrini söyleyecektir. ARG_MAX hakkında, bu doğru. Ancak, kullandığım sistemlerde, ARG_MAX herhangi bir depoda sahip olduğum etiket sayısından çok daha fazla, bu yüzden "ls * .jpg" .
ocroquette

2
en temiz çözüm
mitsest

2
git config --global alias.prune-tags '!git tag -d $(git tag) && git fetch --tags'Zorunlu takma ad komutu. Zevk almak. :-)
Karl Wilbur

87

Git'in son sürümlerine benziyorum (Git v2.20'deyim)

git fetch --prune --prune-tags

Çok daha temiz!

https://git-scm.com/docs/git-fetch#_pruning

Git getirilirken etiketleri her zaman budamak için yapılandırabilirsiniz:

git config fetch.pruneTags true

Etiketleri yalnızca belirli bir uzaktan kumandadan getirilirken budamak istiyorsanız, remote.<remote>.pruneTagsseçeneği kullanabilirsiniz . Örneğin, başlangıç ​​noktasından getirilirken etiketleri her zaman budamak ama diğer uzaktan kumandaları değil,

git config remote.origin.pruneTags true


Mükemmel! Git itme başarısızlığıyla "git-shell sinyal 13'ten öldü" ile karşılaştım. Artan http.postbuffer ile bile etki yok. GIT_TRACE_PACKET ve GIT_TRACE'ı etkinleştirdikten sonra, geçersiz refs / etiketlere aktarmayı gördüm, böylece "--prune-tags" kullanarak sorunu çözdüm. Çok teşekkürler!
Ivellios

78

git fetchV1.7.8'den bu yana Git'in tüm sürümleri bir refspec ile anlaşılırken v1.9.0'dan beri --tagsseçenek seçeneği geçersiz kılar --prune. Genel amaçlı bir çözüm için şunu deneyin:

$ git --version
git version 2.1.3

$ git fetch --prune origin "+refs/tags/*:refs/tags/*"
From ssh://xxx
 x [deleted]         (none)     -> rel_test

Git v1.9.0 sürümünde "--prune" davranışına sahip "--tags" öğesinin nasıl değiştiği hakkında daha fazla bilgi için bkz. Https://github.com/git/git/commit/e66ef7ae6f31f246dead62f574cc2acb75fd001c


7
Bu en iyi cevap olmalı. Bash, pip ve xargs içermeyen tek bir git komutudur.
G. Sylvie Davies

1
Değiştirilen originile upstreamve memba dayalı benim yerel etiketlerini düzeltilmiş git; daha sonra git push origin :<deleted-tag-name>, silinmiş etiketi kaldırarak GitHub çatalımı güncelledi.
leanne

3
En azından git 2.18.0 ile de bu sözdizimini kullanabilirsiniz:git fetch --prune --prune-tags origin
Martin

3
Git 2.17.0 ile başlayarak - --prune-tags seçeneği, aşağıdaki belgede eşdeğer komutlarla PRUNING bölümünde ayrıntılı olarak açıklanmış ve açıklanmıştır: git-scm.com/docs/git-fetch/2.17.0git fetch origin --prune --prune-tags VEYA git fetch origin --prune 'refs/tags/*:refs/tags/*' VEYA git fetch <url of origin> --prune --prune-tags VEYAgit fetch <url of origin> --prune 'refs/tags/*:refs/tags/*'
mkisaacs

8

Git yerel etiketlerin temizlenmesini yerel olarak destekler:

git fetch --tags --prune

Bu komut en son etiketleri çeker ve silinen tüm etiketleri kaldırır.


Görünüşe göre "--prune-tags" yerine "--prune" olmalı, aksi takdirde ihtiyacım olan buydu, teşekkürler.
AnyDev

Kaynak ağacında sorun var bazı refs itmek için başarısız oldu:: Benim için çalışıyor :) Teşekkür Alot
Abhishek Thapliyal


4

Yerel ve uzak etiketler arasındaki farkı göster:

diff <(git tag | sort) <( git ls-remote --tags origin | cut -f2 | grep -v '\^' | sed 's#refs/tags/##' | sort)
  • git tag yerel etiketlerin listesini verir
  • git ls-remote --tags uzak etiketlere giden yolların tam listesini verir
  • cut -f2 | grep -v '\^' | sed 's#refs/tags/##' uzak etiket yolları listesinden yalnızca etiket adını ayrıştırır
  • Sonunda iki listenin her birini sıralıyoruz ve birbirinden ayırıyoruz

"<" İle başlayan satırlar, artık uzak depoda olmayan yerel etiketlerinizdir. Çok azlarsa, bunları tek tek manuel olarak kaldırabilirsiniz, eğer çoklarsa, otomatikleştirmek için daha fazla greping ve borulama yaparsınız.


2
Lütfen kodunuza bir açıklama eklemeyi düşünün. Bu, yanıtınızın kalitesini kesinlikle artıracaktır.
honk

Yerel olarak bulunmayan tüm uzak etiketleri silme komutu şu şekilde olur:diff <(git tag | sort) <( git ls-remote --tags origin | cut -f2 | grep -v '\^' | sed 's#refs/tags/##' | sort) | grep ">" | cut -c3- | xargs -I{} git push origin :refs/tags/{}
Daniel Gehriger

Böyle bir fark yaratmanız ve aynı zamanda taahhüt karmasını görüntülemeniz gerekiyorsa:diff <(git show-ref --tags | grep -v '{}' | awk '{print $1 " " $2}') <(git ls-remote --tags origin | grep -v '{}' | awk '{print $1 " " $2}')
piroux

Bu karşılaştırma tam da aradığım şeydi, teşekkürler. Kafası karıştığım tek şey, aynı zamanda bir okla başlamayan birkaç satır çıktısı <, ancak bir sayı ve ardından bir virgül ve sonra bir kesin karmanın ilk üç karakteri gibi görünen (?), örneğin 7,8d4...
Kay

3

GitHub'da pivotal_git_scripts Gem fork'a bir git sync-local-tags komutu ekledim:

https://github.com/kigster/git_scripts

Gem'i yükleyin, ardından uzaktan kumandada bulunmayan yerel etiketleri silmek için deponuzda "git sync-local-tags" komutunu çalıştırın.

Alternatif olarak, bu komut dosyasını aşağıya yükleyebilir ve "git-sync-local-tags" olarak adlandırabilirsiniz:


#!/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)

3

Partiye geç kaldığımı biliyorum, ama şimdi buna hızlı bir cevap var:

git fetch --prune --prune-tags # or just git fetch -p -P

Evet, şimdi getirme seçeneği.

Getirmek istemiyorsanız ve sadece budamak istiyorsanız:

git remote prune origin

1

Buna ne dersiniz - tüm yerel etiketleri bırakın ve sonra yeniden getirin? Repoyu göz önünde bulundurarak alt modüller içerebilir:

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

1

TortoiseGit şimdi etiketleri karşılaştırabilir.

Sol günlük uzak, sağ yerel.

resim açıklamasını buraya girin

Senkronizasyon iletişim kutusunun Etiketleri karşılaştır özelliğini kullanarak:

resim açıklamasını buraya girin

Ayrıca bkz. TortoiseGit sorunu 2973


1

@Richard W ile aynı cevap ama Windows için (PowerShell)

git tag | foreach-object -process { git tag -d $_ }
git fetch -t

1

Komutu SourceTreeMacOS'umda Özel İşlem olarak ekliyorum .


Ayar Custom Actionstarafından Sourcetree-> Preferences...->Custom Actions


Script to rungityol olmalı .

git fetch --prune --prune-tags originEtiketleri uzaktan yerelden senkronize etmek için kullanıyorum .

resim açıklamasını buraya girin resim açıklamasını buraya girin


0

Yeni git sürümünde (v2.26.2 gibi)

-P, --prune-tags Getirmeden önce, --prune etkinse artık uzaktan kumandada bulunmayan tüm yerel etiketleri kaldırın. Bu seçenek daha dikkatli kullanılmalıdır, --prune'dan farklı olarak oluşturulan tüm yerel başvuruları (yerel etiketler) kaldıracaktır. Bu seçenek, --prune ile birlikte açık etiket refspec'ini sağlamanın bir kısayoludur, bu konudaki belgelere ilişkin tartışmaya bakın.

Yani koşmanız gerekir:

git fetch august --prune --prune-tags
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.