Как мне отредактировать существующее сообщение тега в 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.
dahlbyk

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>и вижу все предыдущие выпуски.
Маноэль Вилела

Проблема в том, что если мне нужно обновить какой-либо тег, который не HEADпроходит, пропуская лишний <commit>, открытый тег становится пустым. Я ожидал, что старый тег просто отредактирует. Есть ли способ?
Маноэль Вилела

Обратите внимание, что решение Энди было обновлено с момента вашего ответа. Возможно, было бы неплохо начать свой ответ с сообщения о том, что он был исправлен? Также может быть, что ваша команда git tag <commit> <tag-name> -f -aпоменяла местами <commit> и <tag-name>? Это выглядит так при сравнении с другими ответами и документами, но я не эксперт.
Джейкоб Аккербум

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) .
(Слиты Junio C Hamano - 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 head имеет версию 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 '"
minterior

1
Просто попробовал это. Вместо того, чтобы давать тегу замены информацию об авторе и дате из самого тега, он использует информацию из фиксации, на которую указывает тег. Это не обязательно то же самое и, по сути, не то же самое для нашего случая большую часть времени. У нас есть инфраструктура мульти-репо, и мы используем аннотированные теги в «репо-ядре» для записи информации о толчках, охватывающих несколько репо. Таким образом, в сущности, указание на коммит может даже не быть частью реального толчка. Информация в аннотированном теге должна отражать реальные толчки в других репо.
Tanager

0

Если вы используете графический интерфейс, как SmartGit просто

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