Удалите локальные теги git, которых больше нет в удаленном хранилище.

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

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

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

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

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

12 ответов

Решение

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

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

Это замечательный вопрос, мне интересно то же самое.

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

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

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

Эти:

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

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

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

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

git fetch <remote> --prune --tags

Обновить

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

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

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

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

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

Похоже на недавние версии Git (я на git v2.20), все просто говорят

git fetch --prune --prune-tags

Гораздо чище!

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

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

$ git tag -d $(git tag)

А затем получить все удаленные теги:

$ git fetch --tags

Все версии 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

В новой версии git (например, v2.26.2)

-P, --prune-tags Перед загрузкой удалите все локальные теги, которые больше не существуют на удаленном компьютере, если --prune включен. Этот параметр следует использовать более осторожно, в отличие от --prune, он удалит все локальные ссылки (локальные теги), которые были созданы. Этот параметр является сокращением для предоставления явного тега refspec вместе с --prune, см. Обсуждение этого в его документации.

Итак, вам нужно запустить:

git fetch august --prune --prune-tags

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

git fetch --tags --prune

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

Я знаю, что опаздываю на вечеринку, но теперь на это есть быстрый ответ:

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

Да, теперь есть возможность получить.

Если вы не хотите получать, а просто обрезать:

git remote prune origin

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

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

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

Тот же ответ, что и у @Richard W, но для Windows (PowerShell)

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

Я добавляю команду в SourceTree как настраиваемое действие в моей MacOS.


Настройка Custom Actions по Sourcetree -> Preferences... -> Custom Actions


Script to run должен быть git дорожка.

я использую git fetch --prune --prune-tags origin для синхронизации тегов с удаленного на локальный.

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

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

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

Просто добавили команду git sync-local-tags в ветвь Gem pivotal_git_scripts на 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)

TortoiseGit теперь может сравнивать теги.

Левый журнал находится на удаленном, правый на локальном.

Использование функции сравнения тегов в диалоге синхронизации:

Также смотрите TortoiseGit выпуск 2973

Как насчет этого - отбросить все локальные теги, а затем повторно получить? Учитывая, что ваше репо может содержать подмодули:

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
Другие вопросы по тегам