リモートリポジトリに存在しないローカルgitタグを削除する


468

デプロイプロセスの一部としてgitでタグを使用します。ときどき、これらのタグをリモートリポジトリから削除してクリーンアップしたいと考えています。

これは非常に簡単です。1人のユーザーが1組のコマンドでローカルタグとリモートタグを削除します。両方の手順を組み合わせた小さなシェルスクリプトがあります。

2番目(3番目、4番目、...)のユーザーに、リモートに反映されなくなったローカルタグが追加されました。

git remote prune originリモートブランチが削除されたローカル追跡ブランチをクリーンアップするのと同様のコマンドを探しています。

または、リモートタグを一覧表示する簡単なコマンドを使用して、を介して返されるローカルタグと比較することもできますgit tag -l


2
古いタグのプルーニングをサポートするgitの新機能を提案しました:thread.gmane.org/gmane.comp.version-control.git/168833
Adam Monsen

1
注:Gitの2.17(Q2 2018年)で、シンプルでgit config fetch.pruneTags true、あなたのようになりますgit fetchあなたがやりたいことを!この他の質問に対する私の答えをください。
VonC 2018年

2
以下の回答の1つからコメントを再投稿:少なくともgit 2.18.0では、次の構文も使用できます:git fetch --prune --prune-tags origin
zutnop

回答:


71

良い質問。:)私は完全な答えを持っていません...

つまり、を介してリモートタグのリストを取得できますgit ls-remote。によって参照されるリポジトリ内のタグを一覧表示するにはorigin、次を実行します。

git ls-remote --tags origin

次のようなハッシュとわかりやすいタグ名のリストが返されます。

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

このリストで生成されたタグとローカルにあるタグを比較するbashスクリプトをまとめることは確かにできます。git show-ref --tagsと同じ形式でタグ名を生成するを見てくださいgit ls-remote


余談ですgit show-refが、あなたが望むものの反対を行うオプションがあります。次のコマンドは、ローカルにないリモートブランチ上のすべてのタグを一覧表示します。

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

マイクありがとう。比較のために各リストを使用して、自分のbashスクリプトをロールバックします。
2009

11
リチャードWの答えは、複雑なスクリプトに興味がない場合に備えて、これをはるかにエレガントに行います。
Kyle Heironimus 2013

1
ローカルによりリモコンをチェックするために拡張することができますタグのない存在についてのサイドノート:git remote | xargs -L 1 git ls-remote --tags | git show-ref --tags --exclude-existing
Palec

より簡単な解決策については、次の回答を参照してください
sfletche

gitは--prune-tagsをサポートしています。これが導入されたバージョンが不明です。 git-scm.com/docs/git-fetch#git-fetch---prune-tags
John Kloian

1054

これは素晴らしい質問です。私も同じことを考えていました。

スクリプトを書きたくなかったので、別の解決策を模索しました。重要なのは、ローカルでタグを削除してから、git fetchを使用してリモートサーバーから「元に戻す」ことができることです。タグがリモートに存在しない場合は、削除されたままになります。

したがって、次の2行を入力する必要があります。

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

これら:

  1. ローカルリポジトリからすべてのタグを削除します。FWIW、xargsは「tag -l」によって出力された各タグを「tag -d」のコマンドラインに配置します。これがなければ、gitはstdinを読み取らないため、何も削除しません(愚かなgit)。

  2. アクティブなタグをすべてリモートリポジトリから取得します。

これはWindowsでもご利用いただけます。


57
これは、StackOverflowで私のお気に入りのgit回答である必要があります。それは知識、シンプルさとトリックを組み合わせ、すべてを説明します。素晴らしい
ティムタム

25
別の回答に記載されているように、これによりすべてのローカルタグが削除され、リモートリポジトリにないタグは明らかに再作成されません
2

13
FWIWこれは完全に不要です。git tag prune originコマンドがあるはずです。
void.pointer 2014年

9
これは誰にとってもうまくいくとは限りません。安全のためにgit fetch --tagsを実行する必要があります。
Adam Kurkiewicz、2015

5
git tag -l | %{git tag -d $_}これをPowerShellで動作させるために行かなければなりませんでした。他の誰かについてはわからない。
Alain

244

Git v1.7.8からv1.8.5.6までは、これを使用できます。

git fetch <remote> --prune --tags

更新

コミットのため、これはgitの新しいバージョン(v1.9.0以降)では機能しません e66ef7ae6f31f2の。一部の人にとってはうまくいったので、私は本当にそれを削除したくありません。

「Chad Juliano」で提案されているように、v1.7.8以降のすべてのGitバージョンでは、次のコマンドを使用できます。

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

ワイルドカードの展開を回避するには、タグ部分を引用符で囲む必要があります(Windowsなど)。

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

2
Git for Windows 1.9.4-preview20140611に同梱されているドキュメントを参照しています(以前のバージョンはすべて疑っています)。私へのアクセスは、彼らが唯一の理由は、デフォルトのタグの自動追従や--tagsオプションによるのフェッチされた場合、「--helpフェッチGIT」[引用]タグ付きドキュメントはプルーニングの対象ではないと述べた[/引用]。
フェリックスCantournet

2
git fetch --prune <remote> +refs/tags/*:refs/tags/*ZSHでは機能しませんでしたが、BASHでは機能しました
Alex

3
@Alexこれは単にzshが拡張され*たからですが、一重引用符で囲んでも問題ありません。
NSF 2016年

3
@ v01pe-ドキュメントの「プルーニング」セクションに記載されているgit 2.17.0以降に使用できるgitショートカット--prune-tagsが追加されました:git-scm.com/docs/git-fetch/2.17.0 ドキュメントから:- -prune-tagsオプションは、リモートのrefspecでrefs / tags / *:refs / tags / *を宣言することと同等です。同等:git fetch origin --prune --prune-tagsOR git fetch origin --prune 'refs/tags/*:refs/tags/*'OR git fetch <url of origin> --prune --prune-tagsORgit fetch <url of origin> --prune 'refs/tags/*:refs/tags/*'
mkisaacs '20 / 09/20

3
git fetch origin --prune --prune-tagsリモート追跡ブランチとタグの両方をプルーニングします。git 2.18バージョンでチェックイン。
Number945

158

リモートに存在するタグのみが必要な場合は、ローカルタグをすべて削除します。

$ git tag -d $(git tag)

そして、すべてのリモートタグをフェッチします。

$ git fetch --tags

1
完璧、タグが見つからないxargsに問題があった
Marcio Toshio

3
@ocroquette、私はそれがどれほど良いかわかりませんxargs。タグがを超えるARG_MAXか、同様の制限がある場合、これは機能しません。ありそうもないが、可能であり、それxargsが素晴らしい理由です。
Paul Draper

2
「ナイス」は主観的なもので、誰もが自分の意見を述べるでしょう。ARG_MAXについては、そうです。ただし、私が使用しているシステムでは、ARG_MAXはどのリポジトリにもあるタグの数よりもはるかに多いため、「ls * .jpg」と書いても気にしないように、制限を気にしません。 。
オコケット

2
最もクリーンなソリューション
2018年

2
git config --global alias.prune-tags '!git tag -d $(git tag) && git fetch --tags'必須のエイリアスコマンド。楽しい。:-)
Karl Wilbur

87

最近のバージョンのGit(私はgit v2.20を使用しています)のように見えるので、簡単に言うことができます

git fetch --prune --prune-tags

ずっときれい!

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

フェッチ時にタグを常に削除するようにgitを設定することもできます。

git config fetch.pruneTags true

特定のリモートからフェッチするときにタグをプルーニングするだけの場合は、 remote.<remote>.pruneTagsオプションできます。たとえば、他のリモートからではなく、オリジンからフェッチするときに常にタグをプルーニングするには、

git config remote.origin.pruneTags true


優秀な!「git-shell dieed of signal 13」でgit pushの失敗に遭遇しました。http.postbufferを増やしても効果はありません。GIT_TRACE_PACKETとGIT_TRACEを有効にした後、「-prune-tags」を使用してそれを解決するために、無効な参照/タグにプッシュするのを見ました。どうもありがとう!
Ivellios

78

v1.7.8以降のGitのすべてのバージョンはrefspecで認識git fetch--tagsますが、v1.9.0以降ではオプションがオプションをオーバーライドし--pruneます。一般的な目的の解決策として、これを試してください:

$ 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での「--prune」動作での「--tags」の変更方法の詳細については、https://github.com/git/git/commit/e66ef7ae6f31f246dead62f574cc2acb75fd001cを参照してください。


7
これが一番の答えになるはずです。これは単一のgitコマンドで、bash、パイプ、xargsはありません。
G.シルビーデイビス

1
交換しoriginupstream上流に基づいて私の地元のタグを修正gitの。次にgit push origin :<deleted-tag-name>、GitHubフォークを更新し、削除されたタグを削除しました。
リーン09/09/22

3
少なくとも、gitの2.18.0 1にもこの構文を使用することができますgit fetch --prune --prune-tags origin
マーティン・

3
git 2.17.0以降---prune-tagsオプションが含まれ、PRUNINGセクションで詳細に説明されています。次のドキュメントの同等のコマンド: git-scm.com/docs/git-fetch/2.17.0 git fetch origin --prune --prune-tags OR git fetch origin --prune 'refs/tags/*:refs/tags/*' OR git fetch <url of origin> --prune --prune-tags ORgit fetch <url of origin> --prune 'refs/tags/*:refs/tags/*'
mkisaacs 2018

8

Gitはローカルタグのクリーンアップをネイティブでサポートしています。

git fetch --tags --prune

このコマンドは、最新のタグを取り込み、削除されたすべてのタグを削除します。


それは「--prune-tags」ではなく「--prune」でなければならないようです、そうでなければそれが私が必要としたものです、ありがとう。
AnyDev 2018

ソースツリーで問題が発生し、いくつかの参照をプッシュできませんでした...:それは私にとっては
うまくいき


4

ローカルタグとリモートタグの違いを表示します。

diff <(git tag | sort) <( git ls-remote --tags origin | cut -f2 | grep -v '\^' | sed 's#refs/tags/##' | sort)
  • git tag ローカルタグのリストを与える
  • git ls-remote --tags リモートタグへのフルパスのリストを提供します
  • cut -f2 | grep -v '\^' | sed 's#refs/tags/##' リモートタグパスのリストからタグ名のみを解析します
  • 最後に、2つのリストをそれぞれソートして、それらを比較します

「<」で始まる行は、リモートリポジトリに存在しないローカルタグです。数が少ない場合は、手動で1つずつ削除できます。数が多い場合は、grepとパイピングを行って自動化します。


2
コードに説明を追加することを検討してください。これにより、回答の質が確実に向上します。
2014年

ローカルに存在しないすべてのリモートのタグを削除するための完全なコマンドは次のようになります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/{}
ダニエルGehriger

そのようなdiffを作成し、同時にコミットハッシュを表示する必要がある場合: diff <(git show-ref --tags | grep -v '{}' | awk '{print $1 " " $2}') <(git ls-remote --tags origin | grep -v '{}' | awk '{print $1 " " $2}')
piroux

この比較はまさに私が探していたものでした、ありがとう。混乱しているのは、矢印<で始まらない2行の出力ですが、数値の後にコンマが続き、コミットハッシュの最初の3文字(?)例7,8d4...
Kay

3

GitHubのpivotal_git_scripts Gem forkにgit sync-local-tagsコマンドを追加しました:

https://github.com/kigster/git_scripts

gemをインストールし、リポジトリで「git sync-local-tags」を実行して、リモートに存在しないローカルタグを削除します。

または、以下のスクリプトをインストールして、「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)

3

私はパーティーに遅れていることを知っていますが、今これに簡単な答えがあります:

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

はい、今ではフェッチするオプションになっています。

フェッチしたくない場合は、プルーニングするだけです。

git remote prune origin

1

これはどうですか?すべてのローカルタグを削除してから再フェッチしますか?リポジトリにサブモジュールが含まれている可能性があることを考慮してください:

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はタグを比較できるようになりました。

左側のログはリモート、右側はローカルです。

ここに画像の説明を入力してください

同期ダイアログのタグ比較機能を使用する:

ここに画像の説明を入力してください

TortoiseGit問題2973も参照してください


1

@Richard Wと同じ回答ですが、Windows向けです(PowerShell)

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

1

コマンドを追加します SourceTree MacOSのカスタムアクションとしてます。


-> -> Custom Actionsによる 設定SourcetreePreferences...Custom Actions


Script to run でなければなりません gitパスで。

git fetch --prune --prune-tags originリモートからローカルにタグを同期するために使用します。

ここに画像の説明を入力してください ここに画像の説明を入力してください


0

新しいgitバージョン(v2.26.2など)

-P、-prune-tags --pruneが有効になっている場合、フェッチする前に、リモートに存在しないローカルタグをすべて削除します。--pruneとは異なり、このオプションはより慎重に使用する必要があります。作成されたローカル参照(ローカルタグ)は削除されます。このオプションは、明示的なタグrefspecを--pruneとともに提供するための省略形です。そのドキュメントの説明を参照してください。

したがって、実行する必要があります:

git fetch august --prune --prune-tags
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.