Edit, 24 Nov 2016: esta resposta é aparentemente popular, por isso estou adicionando uma nota aqui. Se você substituir uma marca em um servidor central, qualquer pessoa que possua a marca antiga - qualquer clone do repositório do servidor central que já tenha a marca - poderá reter sua marca antiga . Portanto, embora isso lhe diga como fazê-lo, tenha certeza de que deseja fazê-lo. Você precisará solicitar a todos que já possuem a tag "errada" para excluir a "tag errada" e substituí-la pela nova "tag correta".
Testar no Git 2.10 / 2.11 mostra que manter a tag antiga é o comportamento padrão para clientes em execução git fetch
, e atualizar é o comportamento padrão para clientes em execução git fetch --tags
.
(A resposta original segue.)
Quando você pede para enviar tags por envio, git push --tags
envia (juntamente com quaisquer confirmações e outros objetos necessários e quaisquer outras atualizações de referência das configurações de envio) para o remoto uma solicitação de atualização do formulário . (Bem, ele envia muitos: um desses para cada tag.)new-sha1 refs/tags/name
A solicitação de atualização é modificada pelo controle remoto para adicionar um old-sha1
(ou novamente, um para cada tag) e depois entregue aos ganchos de pré-recebimento e / ou atualização (os ganchos existentes no controle remoto). Esses ganchos podem decidir se permitem ou rejeitam a tag create / delete / update.
O old-sha1
valor é o SHA-1 "nulo" com todos os zeros se a tag estiver sendo criada. O new-sha1
é o SHA-1 nulo se a tag estiver sendo excluída. Caso contrário, os dois valores SHA-1 são reais e válidos.
Mesmo sem ganchos, existe um tipo de "gancho embutido" que também é executado: o controle remoto se recusará a mover uma tag, a menos que você use o sinalizador "force" (embora o "gancho embutido" esteja sempre bem com os dois "adicionar" e "excluir"). A mensagem de rejeição que você vê é proveniente desse gancho embutido. (Aliás, esse mesmo gancho embutido também rejeita atualizações de ramificações que não são rápidas). 1
Mas - eis uma das chaves para entender o que está acontecendo - a git push
etapa não faz ideia se o controle remoto tem essa tag agora e, se sim, qual o valor do SHA-1. Diz apenas "aqui está minha lista completa de tags, junto com seus valores SHA-1". O controle remoto compara os valores e, se houver adições e / ou alterações, os ganchos serão executados. (Para tags iguais, não faz absolutamente nada. Para tags que você não possui, elas também não fazem nada!)
Se você excluir a tag localmente push
, seu envio simplesmente não transferirá a tag. O controle remoto pressupõe que nenhuma alteração deve ser feita.
Se você excluir a tag localmente, crie-a apontando para um novo local, push
seu push transferirá a tag e o controle remoto verá isso como uma alteração de tag e rejeitará a alteração, a menos que seja um push forçado.
Assim, você tem duas opções:
- fazer um empurrão forçado, ou
- exclua a tag no controle remoto.
O último é possível via git push
2, mesmo que a exclusão local da tag e o push
ing não tenham efeito. Supondo que o nome do controle remoto seja origin
e a tag que você deseja excluir seja dev
:
git push origin :refs/tags/dev
Isso pede ao controle remoto para excluir a tag. A presença ou ausência da tag dev
no seu repositório local é irrelevante; esse tipo de push
, como refspec, é um push de exclusão pura.:remoteref
O controle remoto pode ou não permitir a exclusão de tags (dependendo dos ganchos extras adicionados). Se permitir a exclusão, a tag desaparecerá e, um segundo git push --tags
, quando você tiver uma dev
tag local apontando para algum objeto de repo de tag de confirmação ou anotação, envie sua nova dev
tag. No controle remoto, dev
agora será uma tag recém-criada; portanto, o controle remoto provavelmente permitirá o envio (novamente isso depende de quaisquer ganchos extras adicionados).
O empurrão forçado é mais simples. Se você quiser ter certeza de não atualização qualquer outro do que a tag, basta dizer git push
para empurrar apenas que uma refspec:
git push --force origin refs/tags/dev:refs/tags/dev
(observação: você não precisa --tags
se estiver pressionando explicitamente apenas uma tag ref-spec).
1 Obviamente, o motivo desse gancho interno é ajudar a reforçar o comportamento que outros usuários do mesmo repositório remoto esperam: que ramos não sejam rebobinados e que as tags não sejam movidas. Se você forçar, deve informar os outros usuários que você está fazendo isso, para que eles possam corrigi-lo. Observe que "as tags não se movem" são aplicadas recentemente pelo Git 1.8.2; versões anteriores permitiriam que a tag "avançasse" no gráfico de confirmação, como os nomes das ramificações. Veja as notas de lançamento do git 1.8.2 .
2 É trivial se você puder fazer login no controle remoto. Basta ir ao repositório Git lá e executar git tag -d dev
. Observe que, de qualquer maneira - excluindo a tag no controle remoto ou usando-a git push
para excluí-la -, há um período em que qualquer pessoa que acessa o controle remoto descobre que a dev
tag está ausente. (Eles continuarão a ter sua própria tag antiga, se já a tiverem, e podem até empurrar a tag antiga de volta antes que você possa empurrar a nova.)