Como edito uma mensagem de tag existente no git?

225

Temos várias tags anotadas em nosso repositório git. As tags mais antigas têm mensagens falsas que gostaríamos de atualizar para estar em nosso novo estilo.

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

Neste exemplo, gostaríamos de fazer com que as mensagens v1.x se pareçam com a mensagem v2.0. Alguém sabe como faríamos isso?

jared
fonte
2
Nota: com o Git 2.17 (Q2 2018), um simples git tag -m "A message" --edit v1.0seria suficiente. Veja minha resposta abaixo
VonC
Relacionado: Como você renomeia uma tag Git?
Stevoisiak 16/03/19
@VonC Tentei e recebi fatal: tag 'v6.6.2' already existsusando 2.17.0.
Josh Habdas 26/08/18
1
Você sempre pode excluir a tag anterior e fazê-lo novamente.
RoadRunner

Respostas:

264

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

Isso criará uma nova tag com o mesmo nome (substituindo o original).

Andy
fonte
7
Isso mantém a data da tag original?
James M. Greene
16
Resposta a minha própria comentário pergunta: Sim, não alterar a data. :(
James M. Greene
10
Consulte a seção "Em tags de backdating" em git tag --help.
Dahlbyk
6
Também deve-se notar que você também pode acrescentar várias mensagens (eles são separados por uma nova linha - no GitHub)git tag <tag name> <tag name> -f -m "<new message>" -m "<new message>" -m "<new message>"
Blair McMillan
5
Olhares @ChrisMorley na minha resposta abaixo stackoverflow.com/a/23532519/603949 - em suma, o uso <tag name>^{}quando você deseja substituir oold tag
Sungam
87

Para atualizar uma mensagem complexa, basta especificar a opção de marca anotada com -aou a opção de marca assinada com -s:

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

Isso abrirá um editor com o conteúdo da sua mensagem de tag antiga .

Eric Hu
fonte
39

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

Isso é uma melhoria: sem ^{}ele, será criado um novo objeto de tag que faz referência ao objeto de tag antigo, onde os dois terão o mesmo nome de tag.

<tag name>^{} resolverá a tag / referência até encontrar o primeiro hash de confirmação.

Sungam
fonte
4
@BrentFoust, que funciona apenas quando sua cabeça está no marcado comprometer usage: git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]
Sungam
33

TL; DR

Você pode fazer isso excluindo sua tag e recriando-a enquanto falsifica a data e o autor:

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

Toda a história:

Com base na resposta da Sungram (originalmente proposta como uma edição):

1. Resposta Aceita

Esta é uma melhoria em relação às respostas de Andy e Eric Hu . Suas respostas criarão um novo objeto de tag que faz referência ao objeto de tag antigo e ambos terão o mesmo nome.

Para ilustrar isso, considere o seguinte:

> 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. Melhoria do Sungram

Usar <tag name>^{}como o segundo argumento de git tagexcluirá todas as tags anteriores com o mesmo nome.

Considere a continuação da sessão anterior do terminal:

> 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. Salve a data

Por fim, se você quiser manter a data da tag original como a data da tag atualizada, use alguma mágica awk (ou similar) ou apenas cole a data desejada. A seguir, substitui o segundo exemplo (caso contrário, a data original seria perdida devido à substituição):

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

Referências:

4. DIY

Como alternativa, para atualizar as tags, você pode excluí-las e criá-las novamente. Como se vê, a atualização apenas adiciona uma nova tag e faz com que ela aponte para a antiga, ou, como alternativa, exclui implicitamente a antiga e cria uma nova para apontar para o mesmo commit de qualquer maneira.

Você pode conseguir isso emitindo:

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

Aqui [optional]está um campo opcional; <required>é um campo obrigatório. Obviamente, você pode adicionar qualquer sinalizador após o git tagcomando que normalmente faria.

stanm
fonte
3
Obrigado por apontar que "Suas respostas criarão um novo objeto de tag"!
cwhsu
Citando Andreas Schwab : The tagger is controlled by the committer info. (...) GIT_COMMITTER_{NAME,EMAIL}. A tagger isn't really an author.
Ivan Vučica 01/10
11

A solução da @Andy

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

está errado . Depois disso, com

git show

comando, veremos tags de pilha com o mesmo nome.

Ele adiciona uma nova marca com o mesmo nome e nova mensagem na confirmação <tag-name>. Mas não remove a tag antiga. É um caso especial deste comando:

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

Mas <old-tag>é o mesmo com <tag-name>.


A solução correta é simples, basta atualizar a tag.

git tag <tag-name> -f -a

Lembre-se, apenas um aqui.

Se queremos alterar a tag, o que não é HEAD, precisamos de um <commit>argumento extra .

git tag <commit> <tag-name> -f -a
liuyang1
fonte
SIM! Você está certo. Obrigado por apontar isso. Depois de reescrever a tag anotada algumas vezes, fui verificada git show <tag>e vejo todas as edições anteriores.
Manoel Vilela
O problema é: se eu precisar atualizar uma tag que não é HEAD, passando o extra <commit>, a tag aberta estará vazia. Eu esperava que a tag antiga fosse apenas editada. Existe caminho?
Manoel Vilela
Observe que a solução de Andy foi atualizada desde que você respondeu. Talvez seja bom começar sua resposta com uma mensagem dizendo que foi corrigida? Também pode ser que seu comando git tag <commit> <tag-name> -f -atenha <commit> e <tag-name> revertido? Parece assim quando comparado com outras respostas e documentos, mas não sou especialista.
26619 Jacob Akkerboom
7

gostaríamos de fazer com que as mensagens v1.x se pareçam com a mensagem v2.0

Com o Git 2.17 (Q2 2018), haverá uma alternativa para a criação de uma nova tag git tag <tag name> <tag name> -f -m "<new message>", já que a opção " git tag" aprendeu um explícito " --edit" que permite que a mensagem fornecida por " -m" e " -F" seja editada posteriormente.

Veja commit 9eed6e4 (06 fev 2018) por Nicolas Morey-Chaisemartin ( nmorey) .
(Incorporado por Junio ​​C Hamano - gitster- in commit 05d290e , 06 mar 2018)

tag: adicionar --editopção

Adicione uma --editopção que permita modificar as mensagens fornecidas por -mou -F, da mesma forma git commit --edit.

VonC
fonte
4
Você poderia fornecer um exemplo coerente usando --editesses endereços do OP?
Josh Habdas
@ JoshHabdas, na verdade, você precisa adicionar a opção -f: --edit apenas permite que a mensagem seja editada mais.
VonC 26/08/18
Obrigado. Portanto, se o -fsinalizador for adicionado também, --editele editará a mensagem e modificará o carimbo de data e hora, certo?
Josh Habdas
@ JoshHabdas Essa é a ideia, sim.
VonC 26/08/18
4

Você precisará marcar novamente, usando o -fsinalizador de força.

git tag v1.0 -f -m "actual message"
manojlds
fonte
3
Esta solução supõe que o atual cabeçalho git esteja na versão 1.0. Isso pode atrapalhar as coisas, se não estiver, pois altera a revisão associada à versão 1.0. A solução de Andy evita essa armadilha.
Eric O Lebigot
4

Usando as respostas acima, este é o meu apelido para one-liner .gitconfig. Substitui a tag existente e preserva a data de confirmação.

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

Melhorias?

h0tw1r3
fonte
1
Também mantém o 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 '"
min 25/11
1
Apenas tentei isso. Em vez de fornecer à tag de substituição as informações de autor e data da própria tag, ela usa as informações do commit para o qual a tag aponta. Isso não é necessariamente o mesmo e, de fato, não é o mesmo para o nosso caso na maioria das vezes. Temos uma infraestrutura de vários repositórios e usamos tags anotadas em um repositório 'core' para registrar informações sobre os push que abrangem vários repositórios. Portanto, no núcleo, o commit que está sendo apontado pode nem mesmo fazer parte do impulso real. As informações na tag anotada devem refletir os empurrões reais nos outros repositórios.
tanager
0

Se você estiver usando uma GUI como smartgit apenas

  1. crie a mesma tag novamente na mesma posição com a nova mensagem
  2. escolha "substituir tag existente"
  3. forçar o push da tag para o repositório upstream
rubo77
fonte