Как переименовать тег Git?

1219

Сегодня я просматривал логи проекта и понял, что некоторое время назад я нажал на имя тега. Есть ли способ переименовать тег? Google не нашел ничего полезного.

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

git tag -l

перечисляет его не по порядку относительно всех других тегов. Я понятия не имею, если это важно, но это заставляет меня поверить, что новый объект тега не совсем то, что я хочу. Я могу с этим смириться, потому что мне действительно важно, чтобы имя тега соответствовало документации, но я бы предпочел сделать это «правильно», предполагая, что есть правильный способ сделать это.

Брэндон Фосдик
источник
Использовали ли вы тот же вызов, т. Е. Если старый тег был аннотированным / подписанным тегом, является ли новый тег также таким или легким тегом?
Якуб Наребски
1
И неправильный старый тег, и требуемый новый тег должны быть аннотированы и подписаны. Старый тег был создан с помощью 'git tag -a bad_tag_name', поэтому я хотел бы сделать что-то вроде 'git tag -a good_tag_name'.
Брэндон Фосдик
Я должен отметить, что я также хочу, чтобы этот магический процесс переименования сохранял аннотацию от переименованного тега. На самом деле, я бы очень хотел изменить только имя и больше ничего.
Брэндон Фосдик
7
git log --oneline --decorate --graphполезно при очистке тегов.
Джоэл Пурра
Вы можете переименовать тег в одну строку: см. Мой ответ ниже
VonC

Ответы:

2040

Вот как я переименую тег oldв new:

git tag new old
git tag -d old
git push origin :refs/tags/old
git push --tags

Двоеточие в команде push удаляет тег из удаленного хранилища. Если вы этого не сделаете, Git создаст старую метку на вашем компьютере, когда вы потянете.

Наконец, убедитесь, что другие пользователи удаляют удаленный тег. Пожалуйста, скажите им (коллегам) выполнить следующую команду:

git pull --prune --tags

Обратите внимание, что если вы изменяете аннотированный тег , вам нужно убедиться, что имя нового тега ссылается на базовый коммит, а не на старый объект аннотированного тега, который вы собираетесь удалить. Поэтому используйте git tag -a new old^{}вместо git tag new old(это потому, что аннотированные теги являются объектами, в то время как легкие теги - нет, больше информации в этом ответе ).

Кейси Уотсон
источник
19
если тег аннотирован, новый тег не будет иметь сообщения старого, но это полезная информация
NickSoft,
25
@NickSoft, я только что сделал с аннотированными тегами. Сообщения были скопированы из старого в новое просто отлично. Может быть, у меня есть более новая версия git?
katyhuff
25
git push origin :refs/tags/oldможно упростить, git push origin :oldя думаю.
Джесси Глик
25
Я бы предложил изменить "git push --tags", чтобы он был более явным для этого тега "git push origin refs / tags / new". Вы не хотите случайно нажать другие теги.
криш
11
Предупреждение : Использование git tag new oldсоздаст тег, указывающий на старый тег, а не на фиксацию старого тега. (См. Почему я не могу
оформить
297

Первоначальный вопрос заключался в том, как переименовать тег, что легко: сначала создайте NEW как псевдоним OLD, git tag NEW OLDзатем удалите OLD:git tag -d OLD .

Цитата относительно «пути Git» и (в) здравомыслии не соответствует действительности, потому что она говорит о сохранении имени тега, но заставляет его ссылаться на другое состояние хранилища.

Грег МакГари
источник
3
Ответ выше немного предпочтительнее, поскольку он включает в себя git push originбизнес.
Роли
Самый простой способ, отлично поработать, чтобы переименовать предыдущий тег выпуска, созданный с помощью Gitflow
RousseauAlexandre
5
Предупреждение : Использование git tag new oldсоздаст тег, указывающий на старый тег, а не на фиксацию старого тега. (См. Почему я не могу
оформить
118

В дополнение к другим ответам:

Прежде всего , необходимо создать псевдоним из старого имени тега, указывая на оригинал фиксации:

git tag new old^{}

Затем вам нужно удалить старый локально :

git tag -d old

Затем удалите тег на вашем удаленном местоположении (ях):

# Check your remote sources:
git remote -v
# The argument (3rd) is your remote location,
# the one you can see with `git remote`. In this example: `origin`
git push origin :refs/tags/old

Наконец, вам нужно добавить новый тег в удаленное местоположение. Пока вы этого не сделаете, новые теги не будут добавлены:

git push origin --tags

Повторяйте это для каждого удаленного местоположения.

Помните о последствиях изменения тега Git для потребителей пакета!

кайзер
источник
Предупреждение : Использование git tag new oldсоздаст тег, указывающий на старый тег, а не на фиксацию старого тега. (См. Почему я не могу
оформить
1
@StevenVascellaro Спасибо за ссылку. В следующий раз, пожалуйста, подайте заявку на редактирование - ответы также являются усилиями сообщества. Спасибо.
Кайзер
Я не делал правку, потому что я еще не тестировал код для себя. (Обратите внимание на дату отправки по связанному вопросу)
Stevoisiak
Как только мы это сделаем git tag new old^{}, то нам не нужно git tag new_tag_name old_tag_name(первый шаг).
Number945
28

Если он опубликован, вы не можете удалить его (не рискуя быть заархивированным и обработанным). «Git way» - это сделать:

Нормальная вещь. Просто признай, что ты облажался, и используй другое имя. Другие уже видели одно имя тега, и если вы сохраняете одно и то же имя, вы можете оказаться в ситуации, когда два человека имеют «версию X», но на самом деле они имеют разные «X». Так что просто назовите это «X.1» и покончите с этим.

С другой стороны,

Безумная вещь. Вы действительно хотите также назвать новую версию «X», хотя другие уже видели старую. Так что просто используйте git-tag -f еще раз, как будто вы еще не опубликовали старый.

Это так безумно, потому что:

Git не изменяет (и не должен) изменять теги пользователей. Так что, если кто-то уже получил старый тег, выполнение git-pull на вашем дереве не должно просто заставить их перезаписать старый.

Если кто-то получил от вас тег выпуска, вы не можете просто изменить тег для него, обновив свой собственный. Это большая проблема безопасности, поскольку люди ДОЛЖНЫ иметь возможность доверять своим именам тегов. Если вы действительно хотите сделать безумную вещь, вам нужно просто признать это и сказать людям, что вы все испортили.

Все предоставлено man-страницами .

Роберт Мунтяну
источник
6
Или вы можете пометить (с правильным именем) этот тег с неправильным именем.
Якуб Наребски
6
Спасибо, я уже просматривал эту справочную страницу уже миллион раз. К счастью, плохой тег нигде не был опубликован. Даже если это так, это внутренний проект, и я единственный разработчик (на данный момент). Я думаю, что я достаточно безопасен как от смол, так и от перьев, но только в том случае, если я смогу сделать репо в соответствии с документами.
Брэндон Фосдик
Я иногда использую теги для своих личных ссылок. Например. это может быть тег 'ok_jb'. Я использую это, потому что некоторые люди, с которыми я работаю, не могут собрать для моей платформы, поэтому иногда возникают ошибки сборки. Затем я могу быстро получить версию, которая собирает, проверив этот тег. При сборке новых источников я просто перемещаю тег или переименовываю его в сборки ##, где ## - это число (в зависимости от проекта). Я также могу подчеркнуть, когда была добавлена ​​специальная функция, добавив тег.
7
Плохой ответ. «Не делай этого» никогда не является правильным ответом на вопрос «Как я могу это сделать?». Пользователь не спросил, считаете ли вы, что это хорошая идея, или людям это понравится. Если кто-то спросит: «Как я могу отрезать свою руку?», Либо скажите ему, как это делается, либо оставьте его в покое, но ему не нужно, чтобы кто-то говорил ему, что порезка руки может быть не такой уж хорошей идеей. И вы можете сделать это. Вы можете добавить новый тег и удалить старый, это технически возможно даже в удаленном хранилище.
Меки
5
Кажется, это отвечает на вопрос «Как сделать так, чтобы существующий тег указывал на другую ревизию?» вместо вопроса ОП: «Как мне переименовать тег?» Также неясно, как рассказывать людям, которые вы испортили, это решит проблему (хотя в целом это хорошая идея).
LarsH
25

На этой вики-странице есть интересный однострочный текст, который напоминает нам, что мы можем нажать несколько ссылок :

git push origin <refs/tags/old-tag>:<refs/tags/new-tag> :<refs/tags/old-tag> && git tag -d <old-tag>

и попросить других клонеров сделать git pull --prune --tags

Так что идея состоит в том, чтобы подтолкнуть:

  • <new-tag>для каждых фиксаций , на которые ссылаются <old-tag>: <refs/tags/old-tag>:<refs/tags/new-tag>,
  • удаление<old-tag> ::<refs/tags/old-tag>

См. В качестве примера « Изменить соглашение об именовании тегов в репозитории git? ».

VonC
источник
Сохраняет ли это аннотации?
Брэндон Фосдик
1
Помните, что это оставляет оригинальное имя тега в аннотации для аннотированных тегов !! Я не уверен, подразумевает ли это что-нибудь, хотя, по крайней мере, в текущих версиях.
GBR
@gbr Можете ли вы отредактировать ответ с примером, показывающим, что «оригинальное имя тега» осталось в аннотации?
VonC
1
@VonC Я не уверен, что понимаю, о чем ты спрашиваешь; может быть, я не совсем понял: объекты аннотации содержат поле тега , в котором установлено имя тега, вы можете увидеть его с помощью git cat-file -p <tag>; с вашим методом в моей системе я получаю тэг ref ( <new-tag>) с переименованием , но его поле тэга все еще <old-tag>.
GBR
3
@gbr Разве не то, что хотел ОП? Он упомянул: «Я должен отметить, что я также хочу, чтобы этот магический процесс переименования сохранял аннотацию от переименованного тега. На самом деле, я действительно хотел бы изменить только имя и ничего больше» ( stackoverflow.com/questions/1028649/ How-Do-You-Rename-A-Git-Tag /… )
VonC
25

В качестве дополнения к другим ответам я добавил псевдоним, чтобы сделать все это за один шаг, с более знакомым ощущением команды * nix move. Аргумент 1 - это имя старого тега, аргумент 2 - это имя нового тега.

[alias]
    renameTag = "!sh -c 'set -e;git tag $2 $1; git tag -d $1;git push origin :refs/tags/$1;git push --tags' -"

Применение:

git renametag old new
Джаред Книпп
источник
Это не работает для меня, так как он не на !sh(вопрос был о Windows , Git), однако, после обновления формата в дальнейшем он работал: renametag = "!f() { git tag $2 $1; git tag -d $1; git push origin :refs/tags/$1; git push --tags; }; f".
Солнечный Патель
10

Следуйте трехэтапному подходу для одного или нескольких тегов.

Шаг 1: Определите идентификатор коммита / объекта для коммита, на который указывает текущий тег

     command: git rev-parse <tag name>
     example: git rev-parse v0.1.0-Demo
     example output: db57b63b77a6bae3e725cbb9025d65fa1eabcde

Шаг 2: Удалить тег из хранилища

     command: git tag -d <tag name>
     example: git tag -d v0.1.0-Demo
     example output: Deleted tag 'v0.1.0-Demo' (was abcde)

Шаг 3. Создайте новый тег, указывающий на тот же идентификатор фиксации, на который указывал старый тег

     command: git tag -a <tag name>  -m "appropriate message" <commit id>
     example: git tag -a v0.1.0-full  -m "renamed from v0.1.0-Demo" db57b63b77a6bae3e725cbb9025d65fa1eabcde
     example output: Nothing or basically <No error>

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

викас пакисия
источник
Отсутствуют шаги, чтобы отодвинуть удаленный тэг: git push origin :refs/tags/v0.1.0-Demoи отодвинуть тэги (с другими ожидающими вещами)git push --tags
Star Wolf,
6

Для любителей приключений это можно сделать одной командой:

mv .git/refs/tags/OLD .git/refs/tags/NEW
wolfc
источник
7
Это не сработает, если ваши реффи упакованы, т.е. если вы git gcнедавно запускали
forivall
2
Это также повлияет только на локальный репо. Если у вас настроен пульт, я не уверен, какие негативные последствия это может вызвать. Я не рекомендую этот подход.
Therealklanni
1
Также обратите внимание, что для аннотированных тегов это, вероятно, будет еще более проблематично, поскольку капля «аннотации» среди прочего содержит оригинальное имя тега. На самом деле я не уверен, используется ли это чем-либо (надеюсь, по крайней мере, с помощью тэг-тега), но я бы не рискнул.
GBR
1
@gbr Это работает просто отлично. (Конечно, заметка @forivall должна быть принята во внимание.) Этот прием широко использовался целую вечность в системе сборки ALT Sisyphus. Посмотрите, как хранятся исходные коды для пакета, например: git.altlinux.org/gears/g/gear.git . Читаемые теги, такие как 2.0.7-alt1, представляют собой подписанные теги, представленные сопровождающими в систему сборки. Загадочные теги gb-sisyphus-task164472.200 помещаются туда системой сборки для отслеживания идентификатора задачи, которая собрала и опубликовала pkg из этого источника. Они тупые копии ( cp), с сообщением сопровождающего нетронутым.
imz - Иван Захарящев
@ imz - IvanZakharyaschev Приятно знать, я бы не стал слишком доверять, потому что это не вызовет проблем в будущем с каким-либо продуктом; нет никакой реальной спецификации формата репозиториев git и ожидаемого взаимодействия, поэтому, когда это будет жизнеспособно, я
постараюсь
3

Независимо от проблем, связанных с отправкой тегов и переименованием тегов, которые уже были переданы, в случае, если тег для переименования является аннотированным , вы можете сначала скопировать его благодаря следующей однострочной командной строке:

git tag -a -m "`git cat-file -p old_tag | tail -n +6`" new_tag old_tag^{}

Затем вам просто нужно удалить старый тег:

git tag -d old_tag

Я нашел эту командную строку благодаря следующим двум ответам:

Изменить:
Столкнувшись с проблемами при использовании автоматической синхронизации настроек тегов fetch.pruneTags=true(как описано в https://stackoverflow.com/a/49215190/7009806 ), я лично предлагаю сначала скопировать новый тег на сервер, а затем удалить старый. Таким образом, новый тег не удаляется случайным образом при удалении старого тега, и синхронизация тегов хотела бы удалить новый тег , которого еще нет на сервере . Так, например, все вместе мы получаем:

git tag -a -m "`git cat-file -p old_tag | tail -n +6`" new_tag old_tag^{}
git push --tags
git tag -d old_tag
git push origin :refs/tags/old_tag
Оливье
источник
3

Вы также можете переименовать удаленные теги, не извлекая их, дублируя старый тег / ветку на новое имя и удаляя старое, в одном git push команде.

Удаленный тег переименование / Удаленный филиал → тег конверсия: (Примечание: :refs/tags/)

git push <remote_name> <old_branch_or_tag>:refs/tags/<new_tag> :<old_branch_or_tag>

Удаленный филиал переименовывать / Remote тег → преобразование ветви: (Примечание: :refs/heads/)

git push <remote_name> <old_branch_or_tag>:refs/heads/<new_branch> :<old_branch_or_tag>

Выход переименовывает удаленный тег:

D:\git.repo>git push gitlab App%2012.1%20v12.1.0.23:refs/tags/App_12.1_v12.1.0.23 :App%2012.1%20v12.1.0.23

Total 0 (delta 0), reused 0 (delta 0)
To https://gitlab.server/project/repository.git
 - [deleted]               App%2012.1%20v12.1.0.23
 * [new tag]               App%2012.1%20v12.1.0.23 -> App_12.1_v12.1.0.23
zionyx
источник