Ответ 1
Edit, 24 ноября 2016 года: этот ответ, по-видимому, популярен, поэтому я добавляю здесь примечание. Если вы замените тег на центральном сервере, любой, у кого есть старый тег - любой клон этого репозитория центрального сервера, который уже имеет тег, может сохранить свой старый тег. Поэтому, пока это говорит вам, как это сделать, будьте уверены, вы хотите это сделать. Вам нужно будет заставить всех, у кого уже есть "неправильный" тег, удалить их "неправильный тег" и заменить его новым "правильным тегом".
Тестирование в Git 2.10/2.11 показывает, что сохранение старого тега является поведением по умолчанию для клиентов, работающих под git fetch
, а обновление - поведение по умолчанию для клиентов, работающих под git fetch --tags
.
(Исходный ответ следует.)
Когда вы запрашиваете push-метки, git push --tags
отправляет (вместе с любыми коммитами и другими объектами и любыми другими обновлениями обновления из настроек push) на удаленный запрос на обновление формы new-sha1 refs/tags/name
. (Ну, он посылает сколько угодно: один из них для каждого тега.)
Запрос на обновление изменен удаленным, чтобы добавить old-sha1
(или, опять же, по одному для каждого тега), затем доставляется на крючки предварительного и/или обновления (какие бы крючки не существовали на пульте дистанционного управления). Эти перехватчики могут решить, разрешать или отклонять создание/удаление/обновление тега.
Значение old-sha1
- это все нули "null" SHA-1, если тэг создается. new-sha1
- это пустой SHA-1, если тег удаляется. В противном случае оба значения SHA-1 являются действительными, действительными значениями.
Даже без крючков, есть также "встроенный крюк", который также запускается: пульт отказывается перемещать тег, если вы не используете флаг "force" (хотя "встроенный крючок" всегда ОК с "добавлением" и "удалением" ). Сообщение отклонения, которое вы видите, исходит от этого встроенного крючка. (Кстати, этот же встроенный крючок также отклоняет обновления ветвей, которые не бывают быстрыми.) 1
Но вот один из ключей к пониманию того, что происходит - шаг git push
не знает, есть ли у удаленного этот тег сейчас, и если да, то какое значение имеет значение SHA-1. Он говорит только "здесь полный список тегов, а также их значения SHA-1". Пульт дистанционного управления сравнивает значения и, если есть дополнения и/или изменения, запускает крючки на них. (Для тегов, которые являются одинаковыми, ничего не делает. Для тегов, которые у вас нет, они ничего не делают!)
Если вы удаляете тег локально, то push
, ваш push просто не передает тег. Пульт дистанционного управления не предполагает никаких изменений.
Если вы удаляете тег локально, затем создайте его, указывая на новое место, затем push
, ваш push передает тег, а удаленный видит это как изменение тега и отклоняет изменение, если только это не означает, толчок.
Таким образом, у вас есть два варианта:
- выполните принудительное нажатие или
- удалите тег на пульте дистанционного управления.
Последнее возможно через git push
2 даже если удаление метки локально и push
ing не влияет. Предполагая, что имя пульта origin
, и тег, который вы хотите удалить, dev
:
git push origin :refs/tags/dev
Это указывает удаленному удалению тега. Наличие или отсутствие тега dev
в вашем локальном репозитории не имеет значения; этот тип push
, с :remoteref
как refspec, является удалением чистого удаления.
Пульт дистанционного управления может или не допускать удаление тегов (в зависимости от добавления дополнительных крючков). Если он позволяет удалить, то тег исчезнет, а второй git push --tags
, если у вас есть локальный тег dev
, указывающий на некоторый объект репликации commit или аннотированного тега, отправьте новый тег dev
. На пульте дистанционного управления dev
теперь будет вновь созданным тегом, поэтому пульт, вероятно, позволит нажать (опять же это зависит от добавления дополнительных крючков).
Силовой толчок проще. Если вы хотите быть уверены, что не обновляете ничего, кроме тега, просто скажите git push
нажать только один refspec:
git push --force origin refs/tags/dev:refs/tags/dev
(обратите внимание: вам не нужно --tags
, если вы явно нажимаете только один тег ref-spec).
1 Конечно, причина этого встроенного подключения заключается в том, чтобы обеспечить соблюдение поведения, которое ожидают другие пользователи того же самого удаленного репо: эти ветки не перематываются, а теги не перемещаются, Если вы принудительно нажимаете, вы должны позволить другим пользователям знать, что вы делаете это, чтобы они могли исправить это. Обратите внимание, что "теги вообще не перемещаются" вновь применяется в Git 1.8.2; предыдущие версии позволяли тегу "двигаться вперед" в графе фиксации, подобно именам ветвей. См. git примечания к выпуску 1.8.2.
2Это тривиально, если вы можете войти на пульт. Просто зайдите в репозиторий Git и запустите git tag -d dev
. Обратите внимание, что любой способ - удаление тега на удаленном компьютере или использование git push
для его удаления - есть период времени, когда любой, кто обращается к удаленному компьютеру, обнаружит, что тег dev
отсутствует. (Они будут по-прежнему иметь свой собственный старый тег, если они уже есть, и они могут даже подтолкнуть их старый тег, прежде чем вы сможете нажать новый).