¿Cómo edito un mensaje de etiqueta existente en git?

225

Tenemos varias etiquetas anotadas en nuestro repositorio de git. Las etiquetas más antiguas tienen mensajes falsos que nos gustaría actualizar para que tengan nuestro nuevo estilo.

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

En este ejemplo, nos gustaría hacer que los mensajes v1.x se parezcan al mensaje v2.0. Alguien sabe cómo haríamos esto?

Jared
fuente
2
Nota: con Git 2.17 (Q2 2018), un simple git tag -m "A message" --edit v1.0sería suficiente. Vea mi respuesta a continuación
VonC
@VonC Probó y recibió fatal: tag 'v6.6.2' already existsusando 2.17.0.
Josh Habdas
1
Siempre puede eliminar la etiqueta anterior y volver a hacerlo.
RoadRunner

Respuestas:

264

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

Esto creará una nueva etiqueta con el mismo nombre (sobrescribiendo el original).

Andy
fuente
77
¿Mantiene esto la fecha de la etiqueta original?
James M. Greene
16
Respuesta a mi propia pregunta comentario: Sí, no cambiar la fecha. :(
James M. Greene
10
Consulte la sección "Sobre etiquetas de retroceso" en git tag --help.
dahlbyk
66
También debe tenerse en cuenta que también puede agregar varios mensajes (se separan por una nueva línea, en GitHub)git tag <tag name> <tag name> -f -m "<new message>" -m "<new message>" -m "<new message>"
Blair McMillan
55
@ChrisMorley mira mi respuesta a continuación stackoverflow.com/a/23532519/603949 - en resumen, <tag name>^{}old tag
úsalo
87

Para actualizar un mensaje complejo, solo especifique la opción de etiqueta anotada con -ao la opción de etiqueta firmada con -s:

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

Esto abrirá un editor con el contenido de su antiguo mensaje de etiqueta .

Eric Hu
fuente
39

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

Esto es una mejora: sin ^{} él creará un nuevo objeto de etiqueta que haga referencia al objeto de etiqueta anterior, donde ambos tendrán el mismo nombre de etiqueta.

<tag name>^{} resolverá la etiqueta / referencia hasta que encuentre el primer hash de confirmación.

Sungam
fuente
44
@BrentFoust, eso funciona solo cuando su cabeza está en la confirmación etiquetada usage: git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]
Sungam
33

TL; DR

Puede hacerlo eliminando su etiqueta y volviéndola a crear mientras falsifica la fecha y el autor:

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

Toda la historia:

Basándose en la respuesta de Sungram (originalmente propuesta como una edición):

1. Respuesta aceptada

Esta es una mejora sobre Andy y Eric Hu las respuestas de . Sus respuestas crearán un nuevo objeto de etiqueta que hace referencia al objeto de etiqueta anterior y ambos tendrán el mismo nombre.

Para ilustrar esto, considere lo siguiente:

> 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. Mejora de Sungram

Usar <tag name>^{}como segundo argumento de git tagwill eliminará todas las etiquetas anteriores con el mismo nombre.

Considere la continuación de la sesión terminal anterior:

> 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. Guardar la fecha

Por último, si desea mantener la fecha de la etiqueta original como la fecha de la etiqueta actualizada, use un poco de magia awk (o similar) o simplemente pegue la fecha que desee. El siguiente es un sustituto del segundo ejemplo (de lo contrario, la fecha original se perdería debido a la anulación):

> 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]

Referencias

4. bricolaje

Como alternativa a la actualización de las etiquetas, puede eliminarlas y crearlas nuevamente. Como resultado, la actualización solo agrega una nueva etiqueta y hace que apunte a la anterior, o alternativamente, simplemente elimina implícitamente la anterior y crea una nueva para apuntar a la misma confirmación de todos modos.

Puede lograr esto emitiendo:

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

Aquí [optional]hay un campo opcional; <required>es un campo obligatorio. Por supuesto, puede agregar cualquier indicador después del git tagcomando que normalmente haría.

stanm
fuente
3
¡Gracias por señalar que "Sus respuestas crearán un nuevo objeto de etiqueta"!
cwhsu
Citando a Andreas Schwab : The tagger is controlled by the committer info. (...) GIT_COMMITTER_{NAME,EMAIL}. A tagger isn't really an author.
Ivan Vučica
11

La solución de @Andy

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

es incorrecta . Después de eso, con

git show

comando, veremos etiquetas de pila con el mismo nombre.

Agrega una nueva etiqueta con el mismo nombre de etiqueta y un nuevo mensaje en la confirmación <tag-name>. Pero no elimina la etiqueta vieja. Es un caso especial de este comando:

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

Pero <old-tag>es lo mismo con <tag-name>.


La solución correcta es simple, solo actualizar la etiqueta está bien.

git tag <tag-name> -f -a

Recuerda, solo UNO aquí.

Si queremos cambiar la etiqueta, que no lo es HEAD, necesitamos un <commit>argumento adicional .

git tag <commit> <tag-name> -f -a
liuyang1
fuente
¡SI! Tienes razón. Gracias por señalar eso. Después de volver a escribir la etiqueta anotada varias veces, revisé mi etiqueta git show <tag>y veo todas las ediciones anteriores.
Manoel Vilela
El problema es: si necesito actualizar alguna etiqueta que no lo está HEAD, pasando el extra <commit>, la etiqueta abierta está vacía. Esperaba que la etiqueta anterior solo se editara. ¿Hay camino?
Manoel Vilela
Tenga en cuenta que la solución de Andy se ha actualizado desde que respondió. ¿Quizás sería bueno comenzar su respuesta con un mensaje que diga que se ha solucionado? ¿También podría ser que su comando git tag <commit> <tag-name> -f -atiene <commitir> y <tag-name> invertidos? Se ve de esta manera cuando se compara con otras respuestas y los documentos, pero no soy un experto.
Jacob Akkerboom
7

nos gustaría hacer que los mensajes v1.x se vean como el mensaje v2.0

Con Git 2.17 (Q2 2018), habrá una alternativa a la creación de una nueva etiqueta con git tag <tag name> <tag name> -f -m "<new message>", ya que la opción " git tag" aprendió un explícito " --edit" que permite editar el mensaje dado a través de " -m" y " -F".

Ver commit 9eed6e4 (06 de febrero de 2018) por Nicolas Morey-Chaisemartin ( nmorey) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 05d290e , 06 mar 2018)

tag: agregar --editopción

Agregue una --editopción que permita modificar los mensajes proporcionados por -mo -F, de la misma manera git commit --edit.

VonC
fuente
44
¿Podría por favor proporcionar un ejemplo coherente --editque utilice las direcciones del OP?
Josh Habdas
@JoshHabdas en realidad, debe agregar la opción -f: --edit solo permite que el mensaje se edite más.
VonC
Gracias. Entonces, si -ftambién se agrega la bandera, --editse editará el mensaje y se modificará la marca de tiempo, ¿verdad?
Josh Habdas
@JoshHabdas Esa es la idea, sí.
VonC
4

Deberá etiquetar nuevamente, utilizando la -fbandera de fuerza.

git tag v1.0 -f -m "actual message"
manojlds
fuente
3
Esta solución supone que la cabeza git actual está en la versión 1.0. Esto puede estropear las cosas si no es así, ya que cambia la revisión asociada a la versión 1.0. La solución de Andy evita esta trampa.
Eric O Lebigot
4

Usando las respuestas anteriores, este es mi alias de una línea .gitconfig. Reemplaza la etiqueta existente y conserva la fecha de confirmación.

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

Mejoras?

h0tw1r3
fuente
1
También mantiene el autor: 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
Solo intenté esto. En lugar de dar a la etiqueta de reemplazo la información del autor y la fecha de la etiqueta en sí, utiliza la información del compromiso al que apunta la etiqueta. Esto no es necesariamente lo mismo y, de hecho, no es lo mismo para nuestro caso la mayor parte del tiempo. Tenemos una infraestructura de múltiples repositorios y utilizamos etiquetas anotadas en un repositorio 'central' para registrar información sobre los empujes que abarcan múltiples repositorios. Entonces, en esencia, el compromiso al que se apunta podría ni siquiera ser parte del impulso real. La información en la etiqueta anotada debe reflejar los empujes reales en los otros repositorios.
Tanager
0

Si está utilizando una GUI como smartgit solo

  1. cree la misma etiqueta nuevamente en la misma posición con el nuevo mensaje
  2. elija "sobrescribir etiqueta existente"
  3. forzar-empujar la etiqueta al repositorio ascendente
rubo77
fuente