Удалите локальные теги 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
Эти:
Удалить все теги из локального репо. FWIW, xargs помещает каждый вывод тега с помощью "tag -l" в командную строку для "tag -d". Без этого git ничего не удалит, потому что он не читает stdin (глупый git).
Получить все активные теги из удаленного репо.
Это даже работает на 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
Гораздо чище!
Если вам нужны только те теги, которые существуют на пульте, удалите все свои локальные теги:
$ 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
Тот же ответ, что и у @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