Як перейменувати тег 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

Відповіді:


2038

Ось як я перейменую тег 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 way" та (in) розумності не є базовою, оскільки йдеться про збереження імені тегу, але про те, щоб він посилався на інший стан сховища.


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 Tag має для споживачів пакету!


Попередження : Використання git tag new oldстворить тег, що вказує на старий тег, а не на старий тег. (Див. Чому я не можу
оформити

1
@StevenVascellaro Дякую за посилання. Наступного разу, будь ласка, подайте правки - відповідь - це також зусилля громади. Дякую.
кайзер

Я не робив правки, тому що ще не перевірив код для себе. (Зверніть увагу на дату подання у зв’язаному питанні)
Stevoisiak

Як тільки ми це зробимо git tag new old^{}, тоді нам це не потрібно git tag new_tag_name old_tag_name(перший крок).
Число945

28

Якщо він опублікований, ви не можете його видалити (не ризикуючи потрапити в таріум та пернати, тобто). "Git шлях" - це зробити:

Звичайна річ. Просто визнайте, що ви накрутили, і використовуйте іншу назву. Інші вже бачили одне ім’я тегів, і якщо ви збережете те саме ім’я, ви можете опинитися в ситуації, що двоє людей мають "версію X", але насправді вони мають різні "X". Тому просто називайте це "X.1" і будьте з ним.

Крім того,

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

Це так божевільно, бо:

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

Якщо хтось отримав від вас тег випуску, ви не можете просто змінити тег для них, оновивши власний. Це велика проблема безпеки, оскільки люди ОБОВ'ЯЗКОВО мати змогу довіряти своїм тегам-іменам. Якщо ви дійсно хочете зробити божевільну справу, вам потрібно просто розібратися з цим і сказати людям, що ви заплуталися.

Любність сторінок людини .


6
Або ви можете теги (з правильною назвою) цей неправильно названий тег.
Якуб Нарбський

6
Дякую, я вже переглядав сторінку чоловіка мільйон разів. На щастя, поганий тег ніде не публікувався. Навіть якби це було, це внутрішній проект, і я єдиний розробник (на даний момент). Я думаю, що я досить захищений і від задирки, і від пір'я, але тільки якщо зможу отримати репо, щоб відповідати документам.
Брендон Фосдік,

Я іноді використовую теги для власних особистих довідок. Напр. це може бути тег 'ok_jb'. Я використовую це, тому що деякі люди, з якими я працюю, не можуть створити для моєї платформи, тому іноді виникають помилки в побудові. Потім я можу швидко отримати версію, яка будується, перевіривши цей тег. Коли нові джерела створюються, я просто переміщую тег або перейменую його на build ##, де ## - це число (залежно від проекту). Можу також підкреслити, коли була введена спеціальна функція, додавши тег.

7
Погана відповідь. "Не роби цього" ніколи не є правильною відповіддю на тему "Як я можу це зробити?". Користувач не запитував, чи вважаєте ви, що це гарна ідея зробити це чи людям це сподобається. Якщо хтось запитує "Як я можу відрізати руку", або скажіть йому, як це робиться, або залиште його в спокої, але йому не знадобиться, щоб хтось сказав йому, що різання руки може бути не такою чудовою ідеєю. І ти можеш це зробити. Ви можете додати новий тег і видалити старий, технічно це можливо навіть у віддаленому сховищі.
Mecki

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? ".


Чи зберігає це примітки?
Брендон Фосдік

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

Дотримуйтесь 3-крокового підходу для однієї або декількох тегів.

Крок 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

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 - ІванЗахарящев Добре знати, я б не надто довіряв, хоча це не спричинить проблем у майбутньому з деяким продуктом; немає жодної реальної специфікації формату репозиторіїв git та очікуваної взаємодії, тому, коли це буде життєздатним, я б прагнув робити все чисто якнайменше дивно
gbr

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.