Удалите локальные теги 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