Як відредагувати існуюче повідомлення тегу в git?


225

У нашому репозиторії git у нас є кілька приміток із примітками. Старі теги містять нечіткі повідомлення, які ми хотіли б оновити, щоб вони були в новому стилі.

% git tag -n1
v1.0 message
v1.1 message
v1.2 message
v2.0 Version 2.0 built on 15 October 2011.

У цьому прикладі ми хочемо, щоб повідомлення v1.x виглядали як повідомлення v2.0. Хтось знає, як ми це зробимо?


2
Примітка: з Git 2.17 (Q2 2018) досить просто git tag -m "A message" --edit v1.0. Дивіться мою відповідь нижче
VonC


@VonC Спробував це та отримав fatal: tag 'v6.6.2' already existsза допомогою 2.17.0.
Джош Хабдас

1
Ви завжди можете видалити попередній тег і зробити це знову.
RoadRunner

Відповіді:


264

git tag <tag name> <tag name>^{} -f -m "<new message>"

Це створить новий тег з такою ж назвою (замінивши оригінал).


7
Чи підтримує це дату початкового тегу?
Джеймс М. Грін

16
Відповідь на мій власний коментар питання: Так, це дійсно змінити дату. :(
Джеймс М. Грін

10
Дивіться розділ "Про оновлення тегів" в git tag --help.
дальбик

6
Слід також зазначити, що ви також можете додавати кілька повідомлень (вони відокремлюються новою лінією - на GitHub)git tag <tag name> <tag name> -f -m "<new message>" -m "<new message>" -m "<new message>"
Блер Макміллан

5
@ChrisMorley дивиться мою відповідь нижче stackoverflow.com/a/23532519/603949 - словом, використовуйте, <tag name>^{}коли ви хочете замінитиold tag
Sungam

87

Щоб оновити складне повідомлення, просто вкажіть параметр анотованого тегу з -aабо підписаний варіант тегу за допомогою -s:

git tag <tag name> <tag name>^{} -f -a

Це відкриє редактор із вмістом вашого старого повідомлення з тегом .


39

git tag <tag name> <tag name>^{} -f -a

Це вдосконалення: без ^{}нього буде створено новий об’єкт тегу, що посилається на старий об’єкт тегу, де вони обидва матимуть однакове ім’я тегу.

<tag name>^{} вирішить тег / посилання, поки він не знайде хеш першої фіксації.


4
@BrentFoust, це працює лише тоді, коли ваша голова знаходиться на позначеній usage: git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]
комісії

33

TL; DR

Це можна зробити, видаливши тег і відтворивши його, підробляючи дату та автора:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]

Вся історія:

Спираючись на відповідь Sungram (спочатку пропонувався як редагування):

1. Прийнята відповідь

Це поліпшення щодо відповідей Енді та Еріка Ху . Їх відповіді створять новий об’єкт тегу, який посилається на старий об’єкт тегу, і обидва будуть мати однакове ім’я.

Щоб проілюструвати це, врахуйте наступне:

> git tag tag1 tag1 -f -a  # accepted answer
> git rev-list --objects -g --no-walk --all
[ example output: ]
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
260ab7928d986472895b8c55e54569b3f3cb9517 tag1
a5797673f610914a45ef7ac051e3ee831a6e7c25 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17

> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of updated tag]
[Updated description]

tag tag1
Tagger: [tagger]
Date:   [date of original tag]
[Original description]

[tagged commit details]

2. Поліпшення Sungram

Використовуючи <tag name>^{}як другий аргумент git tag, натомість буде видалено всі попередні теги з тим самим іменем.

Розглянемо продовження попереднього термінального сеансу:

> git tag tag1 tag1^{} -f -a  # suggested improvement
> git rev-list --objects -g --no-walk --all
[ example output: ]
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
75f02acacfd7d91d55b5bcfdfb1f00aebeed15e3 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17 

> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of updated tag]
[Updated description]

[tagged commit details]

3. Збережіть дату

Нарешті, якщо ви хочете зберегти дату початкового тегу як дату оновленого тегу, використовуйте деяку магію awk (або подібну) або просто вставляйте потрібну дату замість цього. Далі наведено заміну другого прикладу (інакше початкова дата втратиться через переоцінку):

> GIT_COMMITTER_DATE="$(git show tag1 |                              # get info about the tag cascade including the date original of the original tag
> awk '{
>     if ($1 == "Date:") {
>         print substr($0, index($0,$3))
>     }
> }' |                                                               # extract all the dates from the info
> tail -2 | head -1)"                                               `# get the second to last date, as the last one is the commit date` \
> git tag tag1 tag1^{} -a -f                                         # finally, update the tag message, but save the date of the old one
>
> git rev-list --objects -g --no-walk --all
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
e18c178f2a548b37799b100ab90ca785af1fede0 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17
> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of original tag]
[Updated description]

[tagged commit details]

Список літератури:

4. Зроби сам

Крім того, щоб оновити теги, ви можете просто видалити їх і створити їх заново. Як виявляється, оновлення просто додає новий тег і робить його вказівкою на старий, або, як альтернативу, просто неявно видаляє старий і створює новий, щоб в будь-якому разі вказувати на те саме виконання.

Ви можете досягти цього, видавши:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]

Тут [optional]необов’язкове поле; <required>є обов'язковим полем. Звичайно, ви можете додати будь-які прапори після git tagкоманди, якою ви зазвичай хотіли б.


3
Дякуємо, що вказали, що "Їх відповіді створять новий об'єкт тегів"!
cwhsu

Цитуючи Андреаса Шваба : The tagger is controlled by the committer info. (...) GIT_COMMITTER_{NAME,EMAIL}. A tagger isn't really an author.
Іван Вучиця

11

Рішення Анді

git tag <tag-name> <tag-name> -f -a

це неправильно . Після нього, с

git show

команда, ми побачимо теги стека з такою ж назвою.

Він додає новий тег з тим же ім'ям тега та нове повідомлення під час фіксації <tag-name>. Але він не видаляє старий тег. Це особливий випадок цієї команди:

git tag [<commit> | <old-tag>] <tag-name>

Але так <old-tag>само і з <tag-name>.


Правильне рішення просте, просто тег оновлення в порядку.

git tag <tag-name> -f -a

Пам'ятайте, тут є лише ОДИН .

Якщо ми хочемо змінити тег, а це не так HEAD, нам потрібен додатковий <commit>аргумент.

git tag <commit> <tag-name> -f -a

ТАК! Ти маєш рацію. Дякуємо, що вказали на це. Після повторного написання тегу, зазначаного в примітці, кілька разів я перевіряв свій тег git show <tag>і бачу всі попередні видання.
Manoel Vilela

Проблема полягає в тому, що якщо мені потрібно оновити тег, який немає HEAD, передаючи зайвий <commit>, відкритий тег порожній. Я очікував, що старий тег просто відредагує. Чи є спосіб?
Manoel Vilela

Зверніть увагу, що рішення Енді було оновлено з моменту відповіді. Можливо, було б непогано розпочати свою відповідь повідомленням, що це було виправлено? Також може бути так, що ваша команда git tag <commit> <tag-name> -f -a<commit> і <tag-name> перетворена? Це виглядає так при порівнянні з іншими відповідями та документами, але я не експерт.
Jacob Akkerboom

7

ми хотіли б, щоб повідомлення v1.x виглядали як повідомлення v2.0

З Git 2.17 (Q2 2018) буде альтернатива створення нового тегу git tag <tag name> <tag name> -f -m "<new message>", оскільки " git tag" вивчила явну " --edit" опцію, яка дозволяє додатково редагувати повідомлення, надане через " -m" та " -F".

Дивіться комісію 9eed6e4 (06 лютого 2018 року) від Ніколя Морея-Кайсемартіна ( nmorey) .
(Об'єднано Хуніо С Хамано - gitster- у комітеті 05d290e , 06 березня 2018 р.)

tag: --editопція додати

Додайте --editопцію, яка дозволяє змінювати повідомлення, надані -mабо -F, таким же чином git commit --edit.


4
Чи можете ви надати узгоджений приклад, використовуючи, --editщо стосується ОП?
Джош Хабдас

@JoshHabdas насправді вам потрібно додати опцію -f: --edit дозволяє лише редагувати повідомлення в подальшому.
VonC

Дякую. Тож якщо -fпрапор буде доданий і тоді --editбуде редагувати повідомлення та змінювати часову позначку , правда?
Джош Хабдас

@JoshHabdas Це ідея, так.
VonC

4

Вам потрібно буде знову позначити тег, використовуючи -fпрапор сили.

git tag v1.0 -f -m "actual message"

3
Це рішення передбачає, що поточна голова git знаходиться у версії 1.0. Це може зіпсувати речі, якщо цього немає, оскільки він змінює версію, пов’язану з версією 1.0. Рішення Енді дозволяє уникнути цієї несподіванки.
Ерік О Лебігот

4

Використовуючи відповіді вище, це мій псевдонім однолінійний .gitconfig. Замінює існуючий тег і зберігає дату фіксації.

[alias]
    tm = "!sh -c 'f() { export GIT_COMMITTER_DATE=$(git log -1 --format=%ci $0); git tag -f -a $0 $0^{}; }; f '"

Поліпшення?


1
Також зберігає автор: tag-amend = "!sh -c 'f() { name=$(git log -1 --format=%an $0); email=$(git log -1 --format=%ae $0); date=$(git log -1 --format=%ci $0); GIT_AUTHOR_NAME=\"${name}\" GIT_COMMITTER _NAME=\"${name}\" GIT_AUTHOR_EMAIL=\"${email}\" GIT_COMMITTER_EMAIL=\"${email}\" GIT_AUTHOR_DATE=\"${date}\" GIT_COMMITTER_DATE=\"${date}\" git tag -f -a $0 $0^{}; }; f '"
мінімум

1
Просто спробував це. Замість того, щоб давати тегу заміни автору та дату інформацію з самого тегу, він використовує інформацію з фіксації, на яку вказує тег. Це не обов'язково однаково і, власне, не є однаковим для нашого випадку більшу частину часу. У нас є інфраструктура мультирепортажного репортажу і використовуємо помічені теги в репозиторії 'core' для запису інформації про натискання, що охоплюють кілька репостів. Таким чином, по суті, вчинення, на яке було звернено увагу, навіть не може бути частиною справжнього поштовху. Інформація в примітці з примітками повинна відображати реальну інформацію в інших репостах.
tanager

0

Якщо ви користуєтесь графічним інтерфейсом, як просто smartgit

  1. створити той же тег знову в тому ж самому місці з новим повідомленням
  2. виберіть "перезаписати існуючий тег"
  3. примусово натисніть тег до сховища вище
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.