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

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

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

У пользователя 2nd (3rd, 4th,...) теперь есть локальные теги, которые больше не отображаются на пульте дистанционного управления.

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

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

Ответ 1

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

Тем не менее, вы можете получить список удаленных тегов через 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 script, чтобы сравнить теги, сгенерированные этим списком, с тегами, которые у вас есть локально. Взгляните на git show-ref --tags, который генерирует имена тегов в той же форме, что и git ls-remote).


В стороне, git show-ref имеет опцию, которая делает противоположное тому, что вы хотите. Следующая команда перечисляет все теги на удаленной ветке, которые у вас локально отсутствуют:

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

Ответ 2

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

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

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

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

Это:

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

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

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

Ответ 3

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

git fetch <remote> --prune --tags

Update

Это не работает в новых версиях Git (начиная с версии v.1.9.0) из-за commit e66ef7ae6f31f2. Я действительно не хочу его удалять, хотя он действительно работает для некоторых людей.

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

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

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

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

Ответ 4

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

$ git tag -d $(git tag)

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

$ git fetch --tags

Ответ 5

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

Ответ 6

Похоже, последние версии 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

Ответ 7

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

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

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

Ответ 8

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

git fetch --tags --prune

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

Ответ 9

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

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

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

Ответ 10

Просто добавлена ​​команда git sync-local-tags для pivotal_git_scripts Gem fork на GitHub:

https://github.com/kigster/git_scripts

Установите драгоценный камень, затем запустите "git sync-local-tags" в вашем репозитории, чтобы удалить локальные теги, которые не существуют на пульте дистанционного управления.

В качестве альтернативы вы можете просто установить этот script ниже и называть его "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)

Ответ 11

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

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

введите описание изображения здесь

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

введите описание изображения здесь

Также см. TortoiseGit issue 2973

Ответ 12

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

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

Ответ 13

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

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