"тег уже существует в удаленной" ошибке после воссоздания тега git

После выполнения следующих шагов я получаю следующую ошибку:

To [email protected]:username/repo-name.git
 ! [rejected]        dev -> dev (already exists)
error: failed to push some refs to '[email protected]:username/repo-name.git'
hint: Updates were rejected because the tag already exists in the remote.
  • Создал репозиторий
  • Клонирование репо на локальной машине.
  • Изменен файл README, внес изменения и нажал фиксацию.
  • Созданный тег dev: git tag dev
  • Вдвинутые теги: git push --tags
  • Изменен файл README, внес изменения и нажал фиксацию.
  • Удаленный тег dev, создал его снова и нажал теги:

    git tag -d dev
    git tag dev
    git push --tags
    

Почему это происходит?

Я нахожусь на Mac. У моих друзей, использующих Linux (Ubuntu), нет этой проблемы. Я знаю, что я могу использовать git push --tags -f для принудительного обновления тега, но это опасно (например, переписывание фиксации производится по ошибке только в теге, а не в ветке).

Ответ 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 отсутствует. (Они будут по-прежнему иметь свой собственный старый тег, если они уже есть, и они могут даже подтолкнуть их старый тег, прежде чем вы сможете нажать новый).

Ответ 2

В Mac SourceTree снимите флажок Push all tags:

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

Ответ 3

Это довольно просто, если вы используете SourceTree.

введите описание изображения здесь В основном вам просто нужно удалить и повторно добавить конфликтующий тег:

  • Перейдите на вкладку Репозиторий Тег Удалить тег
  • Выберите имя конфликтующего тега
  • Отметьте Удалить тег из всех пультов
  • Нажмите Удалить
  • Создайте новый тег с тем же именем для правильной фиксации
  • Обязательно проверьте Нажать все теги, нажав ваши изменения на удаленный

Ответ 4

Если вы хотите использовать тег UPDATE, скажем, 1.0.0

  • git checkout 1.0.0
  • внесите изменения.
  • git ci -am 'modify some content'
  • git tag -f 1.0.0
  • удалить удаленный тег на github: git push origin --delete 1.0.0
  • git push origin 1.0.0

DONE

Ответ 5

Причина, по которой вы получаете отклонено, заключается в том, что ваш тег потерял синхронизацию с удаленной версией. Это то же поведение с ветвями.

синхронизировать с тегом с удаленного устройства через git pull --rebase <repo_url> +refs/tags/<TAG>, и после синхронизации вы должны управлять конфликтами. Если у вас установлен diftool (например, meld) git mergetool meld, используйте его, чтобы синхронизировать удаленный доступ и сохранить свои изменения.

Причина, по которой вы используете флаг - rebase, - это то, что вы хотите поместить свою работу поверх удаленного, чтобы избежать других конфликтов.

Кроме того, я не понимаю, почему вы бы удалили тег dev и заново создали его??? Теги используются для указания версий программного обеспечения или этапов. Пример тегов git v0.1dev, v0.0.1alpha, v2.3-cr (cr - кандидат-релиз) и т.д.


Другим способом решения этой проблемы является вопрос git reflog и переход к моменту нажатия тега dev на удаленном компьютере. Скопируйте идентификатор фиксации и git reset --mixed <commmit_id_from_reflog> таким образом, вы знаете, что ваш тег синхронизирован с удаленным в момент его нажатия и конфликтов не возникает.

Ответ 6

В Windows SourceTree отключите Push all tags to remotes.

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

Ответ 7

Кажется, что я опаздываю на эту проблему и/или на нее уже ответили, но что можно сделать: (в моем случае у меня был только один тег локально, поэтому.. Я удалил старый тег и перезапустил его с помощью:

git tag -d v1.0
git tag -a v1.0 -m "My commit message"

Тогда:

git push --tags -f

Это обновит теги all на удаленном компьютере.

Может быть опасно! Используйте на свой страх и риск.