Удалите локальные теги git, которых больше нет в удаленном хранилище. - PullRequest
406 голосов
/ 03 декабря 2009

Мы используем теги в git как часть нашего процесса развертывания. Время от времени мы хотим очистить эти теги, удалив их из нашего удаленного репозитория.

Это довольно просто. Один пользователь удаляет локальный тег и удаленный тег в одном наборе команд. У нас есть небольшой сценарий оболочки, который объединяет оба этапа.

2-й (3-й, 4-й, ...) пользователь теперь имеет локальные теги, которые больше не отражаются на пульте.

Я ищу команду, аналогичную git remote prune origin, которая очищает локально отслеживаемые ветви, для которых удаленная ветвь была удалена.

В качестве альтернативы можно использовать простую команду для отображения удаленных тегов для сравнения с локальными тегами, возвращаемыми через git tag -l.

Ответы [ 13 ]

935 голосов
/ 21 марта 2011

Это великий вопрос, мне было интересно то же самое.

Я не хотел писать сценарий, поэтому искал другое решение. Ключ обнаруживает, что вы можете удалить тег локально, а затем использовать git fetch, чтобы «вернуть его» с удаленного сервера. Если тег не существует на удаленном компьютере, он останется удаленным.

Таким образом, вам нужно набрать две строки по порядку:

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

Эти:

  1. Удалить все теги из локального репо. FWIW, xargs помещает каждый вывод тега с помощью «tag -l» в командную строку для «tag -d». Без этого git ничего не удалит, потому что он не читает stdin (глупый git).

  2. Получить все активные теги из удаленного репо.

Это даже работает на Windows.

225 голосов
/ 01 мая 2013

От Git v1.7.8 до v1.8.5.6 вы можете использовать это:

git fetch <remote> --prune --tags

Обновление

Это не работает на более новых версиях git (начиная с v1.9.0) из-за коммита e66ef7ae6f31f2 . Я действительно не хочу удалять это, так как это действительно работало для некоторых людей.

Как предложил "Чад Джулиано", со всеми версиями Git начиная с v1.7.8, вы можете использовать следующую команду:

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

Вам может потребоваться заключить часть тегов в кавычки (например, в Windows), чтобы избежать расширения по шаблону:

git fetch --prune <remote> "+refs/tags/*:refs/tags/*"
142 голосов
/ 09 октября 2014

Если вам нужны только те теги, которые существуют на пульте, просто удалите все свои локальные теги:

$ git tag -d $(git tag)

И затем извлеките все удаленные теги:

$ git fetch --tags
73 голосов
/ 02 декабря 2014

Все версии Git начиная с v1.7.8 понимают git fetch с refspec, тогда как с v1.9.0 опция --tags переопределяет опцию --prune. Для решения общего назначения попробуйте это:

$ git --version
git version 2.1.3

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

Подробнее о том, как изменилось поведение «--tags» с «--prune» в Git v1.9.0, смотрите: https://github.com/git/git/commit/e66ef7ae6f31f246dead62f574cc2acb75fd001c

63 голосов
/ 04 декабря 2009

Хороший вопрос. :) У меня нет полного ответа ...

Тем не менее, вы можете получить список удаленных тегов через 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
30 голосов
/ 21 января 2019

Похоже, что последние версии Git (я на git v2.20) позволяют просто сказать

git fetch --prune --prune-tags

Много чище!

https://git -scm.com / Docs / ГИТ-выборки # _pruning

Вы также можете настроить git так, чтобы он всегда удалял теги при извлечении:

git config fetch.pruneTags true

Если вы хотите удалять теги только при извлечении с определенного пульта дистанционного управления, вы можете использовать опцию remote.<remote>.pruneTags. Например, чтобы всегда удалять теги при извлечении из источника, но не с других пультов,

git config remote.origin.pruneTags true
7 голосов
/ 06 апреля 2018

Git изначально поддерживает очистку локальных тегов:

git fetch --tags --prune

Эта команда извлекает последние теги и удаляет все удаленные теги.

7 голосов
/ 19 февраля 2018

это хороший метод:

git tag -l | xargs git tag -d && git fetch -t

Источник: demisx.GitHub.io

4 голосов
/ 15 октября 2014

Показать разницу между локальными и удаленными тегами:

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/##' анализирует только имя тега из списка путей удаленного тега
  • Наконец, мы сортируем каждый из двух списков и различаем их

Строки, начинающиеся с «<», - это ваши локальные теги, которых больше нет в удаленном репо. Если их немного, вы можете удалить их вручную один за другим, если их много, вы сделаете больше операций по нарезке и обвязке для их автоматизации. </p>

3 голосов
/ 14 декабря 2010

Только что добавил команду git sync-local-tags в pivotal_git_scripts Gem fork на GitHub:

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)
...