Como você renomeia uma tag Git?

1219

Hoje eu estava procurando nos logs um projeto e percebi que havia digitado o nome de uma tag há algum tempo. Existe alguma maneira de renomear a tag? O Google não encontrou nada útil.

Sei que pude verificar a versão marcada e criar uma nova tag, até tentei isso. Mas isso parece criar um objeto de tag que não está certo. Para um,

git tag -l

lista fora de ordem em relação a todas as outras tags. Não tenho idéia se isso é significativo, mas isso me leva a acreditar que o novo objeto de tag não é exatamente o que eu quero. Eu posso viver com isso, porque realmente me importo apenas que o nome da tag corresponda à documentação, mas prefiro fazê-lo "certo", assumindo que haja uma maneira correta de fazer isso.

Brandon Fosdick
fonte
Você usou a mesma invocação, ou seja, se a tag antiga foi anotada / assinada, a nova tag também é desse tipo ou é leve?
Jakub Narębski
1
A tag antiga incorreta e a nova tag desejada devem ser anotadas e sem sinal. A tag antiga foi criada com 'git tag -a bad_tag_name', então eu gostaria de fazer algo como 'git tag -a good_tag_name'.
Brandon Fosdick
Devo salientar que também quero que esse processo de renomeação de marca mágica preserve a anotação da marca que está sendo renomeada. Na verdade, eu realmente gostaria de mudar apenas o nome e nada mais.
Brandon Fosdick
7
git log --oneline --decorate --graphé útil ao limpar tags.
Joel Purra
Você pode renomear uma tag em uma linha: veja minha resposta abaixo
VonC:

Respostas:

2039

Aqui está como renomeio uma tag oldpara new:

git tag new old
git tag -d old
git push origin :refs/tags/old
git push --tags

Os dois pontos no comando push removem a marca do repositório remoto. Se você não fizer isso, o Git criará a tag antiga na sua máquina quando você puxar.

Por fim, verifique se os outros usuários removem a tag excluída. Diga a eles (colegas de trabalho) para executar o seguinte comando:

git pull --prune --tags

Observe que, se você estiver alterando uma tag anotada , precisará garantir que o novo nome da tag esteja referenciando a confirmação subjacente e não o antigo objeto de tag anotada que você está prestes a excluir. Portanto, use em git tag -a new old^{}vez de git tag new old(isso ocorre porque as tags anotadas são objetos e as tags leves não, mais informações nesta resposta ).

Casey Watson
fonte
19
se tag é anotado o novo tag não terá a mensagem do antigo, mas é uma informação útil
NickSoft
25
@ NickSoft, acabei de fazer o acima com tags anotadas. As mensagens foram copiadas da antiga para a nova. Talvez eu tenha uma versão mais recente do git?
precisa saber é o seguinte
25
git push origin :refs/tags/oldpode ser simplificado, git push origin :oldeu acho.
Jesse Glick 28/01
25
Eu sugeriria que a alteração "git push --tags" seja mais explícita para esta tag "git push origin refs / tags / new". Você não deseja empurrar inadvertidamente outras tags.
chrish 14/05
11
Aviso : O uso git tag new oldcriará uma marca apontando para a marca antiga, não para a confirmação da marca antiga. (Veja Por que não posso conferir meu tag de Git GUI? )
Stevoisiak
297

A pergunta original era como renomear uma tag, o que é fácil: primeiro crie NEW como um apelido de OLD: git tag NEW OLDdepois exclua OLD:git tag -d OLD .

A citação sobre "o caminho do Git" e a (in) sanidade está fora da base, porque se trata de preservar um nome de marca, mas fazendo com que se refira a um estado de repositório diferente.

Greg McGary
fonte
3
A resposta acima é um pouco preferível, pois inclui os git push originnegócios.
Roly 29/09
da maneira mais fácil, trabalhe muito bem para renomear uma tag de versão anterior criada com o Gitflow
RousseauAlexandre
5
Aviso : O uso git tag new oldcriará uma marca apontando para a marca antiga, não para a confirmação da marca antiga. (Veja Por que não posso conferir meu tag de Git GUI? )
Stevoisiak
118

Além das outras respostas:

Primeiro, você precisa criar um alias do nome da tag antiga , apontando para o commit original:

git tag new old^{}

Então você precisa excluir o antigo localmente :

git tag -d old

Em seguida, exclua a tag em seus locais remotos:

# 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

Finalmente, você precisa adicionar sua nova tag ao local remoto. Até você fazer isso, as novas tags não serão adicionadas:

git push origin --tags

Repita isso para todos os locais remotos.

Esteja ciente das implicações que uma alteração no Git Tag tem para os consumidores de um pacote!

kaiser
fonte
Aviso : O uso git tag new oldcriará uma marca apontando para a marca antiga, não para a confirmação da marca antiga. (Veja Por que não posso conferir meu tag de Git GUI? )
Stevoisiak
1
@StevenVascellaro Obrigado pelo link. Para a próxima vez, registre um edição - responder também é um esforço da comunidade. Obrigado.
precisa
Não fiz uma edição porque ainda não testei o código. (Observe a data de envio na pergunta vinculada)
Stevoisiak
Quando o fizermos git tag new old^{}, não precisamos git tag new_tag_name old_tag_name(o primeiro passo).
945
28

Se for publicado, você não poderá excluí-lo (sem correr o risco de ser asfaltado e difuso). A 'maneira Git' é fazer:

A coisa são. Apenas admita que você errou e use um nome diferente. Outros já viram um nome de tag e, se você mantiver o mesmo nome, pode estar na situação em que duas pessoas têm a "versão X", mas na verdade têm "X" diferentes. Então, basta chamá-lo de "X.1" e terminar com isso.

Alternativamente,

A coisa louca. Você realmente deseja chamar a nova versão de "X" também, mesmo que outros já tenham visto a antiga. Portanto, basta usar git-tag -f novamente, como se você não tivesse publicado o antigo.

É tão insano porque:

O Git não altera (e não deve) alterar as tags nas costas dos usuários. Portanto, se alguém já recebeu a etiqueta antiga, dar um puxão na sua árvore não deve fazê-la substituir a antiga.

Se alguém recebeu uma etiqueta de liberação de você, você não pode simplesmente alterá-la atualizando a sua. Esse é um grande problema de segurança, pois as pessoas DEVEM confiar em seus nomes de tags. Se você realmente quer fazer a coisa insana, precisa apenas confessar e dizer às pessoas que você errou.

Toda cortesia das páginas de manual .

Robert Munteanu
fonte
6
Ou você pode marcar (com o nome correto) essa marca com nome incorreto.
Jakub Narębski
6
Obrigado, eu já estive nessa página de manual um milhão de vezes. Felizmente, a etiqueta incorreta não foi publicada em nenhum lugar. Mesmo que fosse, esse é um projeto interno e sou o único desenvolvedor (no momento). Eu acho que estou bastante seguro tanto da alcatrão quanto da penugem, mas apenas se conseguir que o repo corresponda aos documentos.
Brandon Fosdick
Às vezes, uso tags para minhas próprias referências pessoais. Por exemplo. poderia ser uma tag 'ok_jb'. Eu uso isso, porque algumas das pessoas com quem trabalho não podem criar para minha plataforma; portanto, às vezes, há erros de compilação. Posso então obter rapidamente uma versão criada, verificando essa tag. Quando as novas fontes são construídas, apenas movo a tag ou a renomeio para compila ##, em que ## é um número (dependendo do projeto). Também posso enfatizar quando um recurso especial foi introduzido, adicionando uma tag.
7
Má resposta. "Não faça" nunca é a resposta correta para "Como posso fazer isso?". O usuário não estava perguntando se você acha que é uma boa ideia fazer isso ou se as pessoas vão gostar disso. Se alguém perguntar "Como posso cortar minha mão", diga-lhe como é feito ou deixe-o em paz, mas ele não precisará de alguém que lhe diga que cortar uma mão pode não ser uma ótima idéia. E você pode fazer isso. Você pode adicionar uma nova tag e excluir a antiga, é tecnicamente possível, mesmo em um repositório remoto.
Mecki
5
Isso parece responder à pergunta "Como faço para que uma tag existente aponte para uma revisão diferente?" em vez da pergunta do OP, "Como renomear uma tag?" Também não está claro como dizer às pessoas que você errou vai resolver o problema (mesmo que seja uma boa ideia em geral).
Larsh
25

Esta página da wiki possui uma linha interessante, que nos lembra que podemos enviar várias referências :

git push origin <refs/tags/old-tag>:<refs/tags/new-tag> :<refs/tags/old-tag> && git tag -d <old-tag>

e pedir a outros clonadores para fazer git pull --prune --tags

Portanto, a ideia é pressionar:

  • <new-tag>para cada commits referenciados por <old-tag>: <refs/tags/old-tag>:<refs/tags/new-tag>,
  • a exclusão de<old-tag> ::<refs/tags/old-tag>

Veja como um exemplo " Alterar a convenção de nomenclatura de tags dentro de um repositório git? ".

VonC
fonte
Isso preserva anotações?
precisa
1
Cuidado, pois isso deixa o nome da tag original na anotação para tags anotadas !! Não tenho certeza se isso realmente implica alguma coisa, pelo menos nas versões atuais.
GBR
@gbr Você pode editar a resposta com um exemplo que mostra que o "nome da tag original" permaneceu na anotação?
VonC 20/08/2015
1
@VonC Não sei ao certo o que você está perguntando; talvez eu não tenha sido claro: os objetos de anotação contêm um campo de tag definido como o nome da tag, você pode vê-lo git cat-file -p <tag>; com seu método no meu sistema, recebo a tag 'renomeada' ref ( <new-tag>), mas seu campo de tag ainda é <old-tag>.
precisa
3
@gbr Não é o que o OP queria? Ele mencionou "Devo salientar que também quero que esse processo de renomeação de marca mágica preserve a anotação da marca que está sendo renomeada. Na verdade, eu realmente gostaria de mudar apenas o nome e nada mais" ( stackoverflow.com/questions/1028649/ como-renomeia-uma-tag-git /… )
VonC
25

Como um complemento para as outras respostas, adicionei um alias para fazer tudo em uma única etapa, com uma sensação mais familiar do comando * nix move. Argumento 1 é o nome da marca antiga, argumento 2 é o novo nome da marca.

[alias]
    renameTag = "!sh -c 'set -e;git tag $2 $1; git tag -d $1;git push origin :refs/tags/$1;git push --tags' -"

Uso:

git renametag old new
Jared Knipp
fonte
Isto não funcionou para mim, já que falhou em !sh(pergunta foi sobre o Windows Git), no entanto, depois de atualizar o formato para o seguinte, funcionou: renametag = "!f() { git tag $2 $1; git tag -d $1; git push origin :refs/tags/$1; git push --tags; }; f".
Sunny Patel
10

Siga a abordagem em três etapas para um ou alguns números de tags.

Etapa 1: Identifique o ID do objeto / confirmação do commit que a tag atual está apontando

     command: git rev-parse <tag name>
     example: git rev-parse v0.1.0-Demo
     example output: db57b63b77a6bae3e725cbb9025d65fa1eabcde

Etapa 2: excluir a tag do repositório

     command: git tag -d <tag name>
     example: git tag -d v0.1.0-Demo
     example output: Deleted tag 'v0.1.0-Demo' (was abcde)

Etapa 3: crie uma nova tag apontando para o mesmo ID de confirmação que a tag antiga estava apontando para

     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>

Quando o git local estiver pronto com a alteração do nome da tag, essas alterações poderão ser enviadas de volta à origem para que outras pessoas as aceitem.

vikas pachisia
fonte
Está faltando etapas para empurrar tag volta excluído: git push origin :refs/tags/v0.1.0-Demoe empurrar as etiquetas para trás (com outras coisas pendentes)git push --tags
Star Wolf
6

Para os aventureiros, isso pode ser feito em um comando:

mv .git/refs/tags/OLD .git/refs/tags/NEW
wolfc
fonte
7
Isso não funcionará se os seus git gc
árbitros estiverem prontos
2
Isso também afetará apenas o repositório local. Se você tiver um controle remoto configurado, não tenho certeza de quais efeitos negativos isso pode causar. Eu não recomendo esta abordagem.
Therealklanni # 9/13
1
Observe também que, para tags anotadas, isso provavelmente será ainda mais problemático, pois o blob 'anotação' entre outras coisas contém o nome original da tag. Na verdade, não tenho certeza se isso é usado por alguma coisa (espero, pelo menos, pela etiqueta de verificação), mas não me arriscaria.
GBR
1
@gbr Isso funciona muito bem (é claro que a nota de @forivall deve ser levada em consideração.) Esse truque tem sido usado massivamente há séculos no sistema de compilação ALT Sisyphus. Veja como as fontes de um pacote são armazenadas, por exemplo: git.altlinux.org/gears/g/gear.git . As tags legíveis como 2.0.7-alt1 são as tags assinadas enviadas pelos mantenedores ao sistema de compilação. As tags criptográficas gb-sisyphus-task164472.200 são colocadas no sistema de build para rastrear o ID da tarefa que criou e publicou o pkg a partir dessa fonte. São cópias idiotas ( cp), com a mensagem do mantenedor intocada.
imz - Ivan Zakharyaschev
@ imz - IvanZakharyaschev É bom saber que, embora não confiasse demais, isso não causaria problemas no futuro, com algum produto; não há nenhuma especificação do formato de repositórios git e interação esperado, por isso, quando é viável que eu iria se esforçar para fazer as coisas de forma limpa no mínimo surpreendente maneira
GBR
3

Independentemente dos problemas relacionados ao envio de tags e renomeação de tags que já foram enviadas, caso a tag a renomear seja uma anotada , primeiro você poderá copiá-la graças à seguinte linha de comando de linha única:

git tag -a -m "`git cat-file -p old_tag | tail -n +6`" new_tag old_tag^{}

Então, você só precisa excluir a tag antiga:

git tag -d old_tag

Encontrei esta linha de comando graças às duas respostas a seguir:

Edit:
Depois de ter encontrado problemas com sincronização automática de etiquetas de configuração fetch.pruneTags=true(como descrito na https://stackoverflow.com/a/49215190/7009806 ), eu, pessoalmente, sugiro que primeiro copie o novo tag no servidor e , em seguida, apagar o antigo. Dessa forma, a nova tag não é excluída aleatoriamente ao excluir a tag antiga e a sincronização das tags gostaria de excluir a nova tag que ainda não está no servidor . Então, por exemplo, todos juntos temos:

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
Olivier
fonte
3

Você também pode renomear tags remotas sem retirá-las, duplicando a tag / ramificação antiga para um novo nome e excluindo o antigo, em um único git push comando.

Tag de mudança de nome remoto / ramo remoto → conversão tag: (Aviso: :refs/tags/)

git push <remote_name> <old_branch_or_tag>:refs/tags/<new_tag> :<old_branch_or_tag>

Renomeação ramo remoto / tag remoto → conversão ramo: (Aviso: :refs/heads/)

git push <remote_name> <old_branch_or_tag>:refs/heads/<new_branch> :<old_branch_or_tag>

Saída renomeando uma tag remota:

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
zionyx
fonte