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


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

To git@provider.com:username/repo-name.git
 ! [rejected]        dev -> dev (already exists)
error: failed to push some refs to 'git@provider.com:username/repo-name.git'
hint: Updates were rejected because the tag already exists in the remote.
  1. создал репозиторий
  2. клонировал РЕПО на локальном компьютере.
  3. изменил файл README, внес изменения и нажал фиксацию.
  4. создал тег dev:git tag dev
  5. толкнул теги: git push --tags
  6. изменил файл README, внес изменения и нажал фиксацию.
  7. удалил тег dev , создал его снова и нажал теги:

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

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

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

7 120

7 ответов:

Edit, 24 Nov 2016: этот ответ, по-видимому, популярен, поэтому я добавляю Примечание здесь. Если вы заменить метку на центральном сервере, любой, кто имеет старый тег-любой клон этого репозитория центрального сервера, который уже имеет тег-может сохранить свой старый тег. Так что пока это говорит вам, как это сделать, будьте действительно уверены, что вы хочу сделать это. Вам нужно будет удалить всех, у кого уже есть "неправильный" тег их "неправильный тег "и заменить его на новый"правильный тег".

тестирование в Git 2.10 / 2.11 показывает, что сохранение старого тега является поведением по умолчанию для клиентов, работающих под управлением git fetch, и обновление является поведением по умолчанию для клиентских компьютеров под управлением git fetch --tags.

(оригинальный ответ ниже.)


когда вы просите нажать теги,git push --tags отправляет (вместе с любыми фиксациями и другими необходимыми объектами и любыми другими обновлениями ref из настроек push) на удаленный запрос на обновление формы new-sha1 refs/tags/name. (Ну, он посылает сколько угодно: один из них для каждого тега.)

запрос на обновление изменяется пультом дистанционного управления для добавления old-sha1 (или снова, по одному для каждого тега), затем доставляется на крючки предварительного приема и/или обновления (в зависимости от того, какие крючки существуют на пульте дистанционного управления). Эти крючки могут решить, разрешить или отклонить тег create/delete / update.

The old-sha1 значение-это все нули "null" SHA-1, если тег находится создан. Элемент new-sha1 является нулевым SHA-1, если тег удаляется. В противном случае оба значения SHA-1 являются реальными, допустимыми значениями.

даже без крючков есть своего рода" встроенный крючок", который также запускается: пульт дистанционного управления откажется перемещать тег, если вы не используете флаг" force "(хотя" встроенный крючок "всегда в порядке как с" add", так и с"delete"). Сообщение об отказе, которое вы видите, исходит от этого встроенного крючка. (Кстати, этот же встроенный крючок тоже отвергает обновления ветвей, которые не являются быстрыми вперед.)1

но-вот один из ключей к пониманию того, что происходит-в git push шаг понятия не имеет, есть ли у пульта ДУ этот тег сейчас, и если да, то какое значение SHA-1 он имеет. Он только говорит: "Вот мой полный список тегов вместе с их значениями SHA-1". Удаленный сравнивает значения и если есть дополнения и/или изменения, запускает крючки на них. (Для тегов, которые одинаковы, он вообще ничего не делает. Для тегов, которых у вас нет что они делают, он тоже ничего не делает!)

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

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

таким образом, у вас есть два опции:

  • сделайте силовой толчок, или
  • удалить тег на пульте.

последний и через git push2 даже если удалить тег локально и pushing не имеет никакого эффекта. Предполагая, что имя пульта дистанционного управления origin, и тег, который вы хотите удалить, это dev:

git push origin :refs/tags/dev

это просит пульт дистанционного управления, чтобы удалить тег. Наличие или отсутствие тега dev в вашей локальный репозиторий не имеет значения; этот вид push С :remoteref как refspec, является чисто-удалить толчок.

пульт дистанционного управления может разрешать или не разрешать удаление тегов (в зависимости от добавленных дополнительных крючков). Если он позволяет удаление, то тег исчезнет, а второй git push --tags, когда у вас есть локальная dev тег, указывающий на какой-либо объект commit или annotated tag repo, Отправьте свой новый 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 тег отсутствует. (Они будут продолжать иметь собственные старый тег, если он у них уже есть, и они могут даже нажать их старый тег обратно, прежде чем вы можете нажать на новый.)

в Mac SourceTree только снимите флажок нажимаем все теги:

enter image description here

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

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

  1. перейдите на вкладку хранилище -> Tag ->Удалить Тег
  2. выберите конфликтующее имя тега
  3. Регистрация удалить тег со всех пультов
  4. пресс удалить
  5. создать новый тег с тем же именем для правильной фиксации
  6. проверьте нажимаем все теги при нажатии ваши изменения в remote

если вы хотите обновление тег, скажем 1.0.0

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

сделал

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

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

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

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


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

в Windows SourceTree, снимите галочку Push all tags to remotes.

enter image description here

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

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

затем:

git push --tags -f

что все теги на пульте дистанционного управления.

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