Edytuj, 24 listopada 2016 r .: ta odpowiedź jest najwyraźniej popularna, więc dodaję tutaj notatkę. Jeśli zastąpić tag na centralnym serwerze, kto ma stary Tag-dowolny klon tego repozytorium centralnego serwera, który ma już tag-mogła zachować swój stary znacznik . Więc chociaż mówi ci, jak to zrobić, upewnij się, że chcesz to zrobić. Będziesz musiał poprosić wszystkich, którzy mają już „zły” tag, aby usunął swój „zły tag” i zastąpił go nowym „właściwym tagiem”.
Testowanie w Git 2.10 / 2.11 pokazuje, że zachowanie starego tagu jest domyślnym zachowaniem dla działających klientów git fetch
, a aktualizacja jest domyślnym zachowaniem dla działających klientówgit fetch --tags
.
(Oryginalna odpowiedź jest następująca.)
Kiedy prosisz o wypchnięcie tagów, git push --tags
wysyła (wraz z wszelkimi zatwierdzeniami i innymi potrzebnymi obiektami oraz innymi aktualizacjami referencyjnymi z ustawień wypychania) do pilota żądanie aktualizacji formularza . (Cóż, wysyła dowolną liczbę: po jednym dla każdego tagu.)new-sha1 refs/tags/name
Żądanie aktualizacji jest modyfikowane przez pilota w celu dodania old-sha1
(lub ponownie jednego dla każdego znacznika), a następnie dostarczane do zaczepów przed odbiorem i / lub aktualizacją (niezależnie od tego, które z zaczepów istnieją na pilocie). Te haki mogą decydować, czy zezwolić, czy odrzucić tworzenie / usuwanie / aktualizację znacznika.
old-sha1
Wartość jest all-Zera „null” SHA-1, jeśli znacznik jest tworzony. To new-sha1
jest zerowy SHA-1, jeśli tag jest usuwany. W przeciwnym razie obie wartości SHA-1 są rzeczywistymi, prawidłowymi wartościami.
Nawet bez haków istnieje rodzaj „wbudowanego haka”, który jest również uruchamiany: pilot odmówi przeniesienia taga, chyba że użyjesz flagi „wymuś” (chociaż „wbudowany zaczep” jest zawsze OK z obydwoma „dodaj” i „usuń”). Komunikat o odrzuceniu, który widzisz, pochodzi z tego wbudowanego hooka. (Nawiasem mówiąc, ten sam wbudowany punkt zaczepienia odrzuca również aktualizacje gałęzi, które nie są szybkie do przodu.) 1
Ale - oto jeden z kluczy do zrozumienia, co się dzieje - git push
krok nie ma pojęcia, czy pilot ma teraz ten znacznik, a jeśli tak, jaką ma wartość SHA-1. Mówi tylko „oto moja pełna lista tagów, wraz z ich wartościami SHA-1”. Pilot porównuje wartości i jeśli są dodatki i / lub zmiany, uruchamia na nich przechwyty. (W przypadku tagów, które są takie same, w ogóle nic nie robi. W przypadku tagów, których nie masz, to one również nie robią!)
Jeśli usuniesz tag lokalnie, to push
naciśnięcie po prostu nie przenosi tagu. Pilot zakłada, że nie należy wprowadzać żadnych zmian.
Jeśli usuniesz tag lokalnie, a następnie utwórz go wskazując nowe miejsce, wtedy push
twoje naciśnięcie przenosi tag, a pilot postrzega to jako zmianę tagu i odrzuca zmianę, chyba że jest to wymuszenie.
Masz więc dwie możliwości:
- zrobić pchnięcie siłowe lub
- usuń znacznik na pilocie.
To ostatnie jest możliwe za pomocą git push
2, mimo że lokalne usunięcie taga i push
nie ma żadnego efektu. Zakładając, że nazwa pilota to origin
, a tag, który chcesz usunąć, to dev
:
git push origin :refs/tags/dev
To prosi pilota o usunięcie tagu. Obecność lub brak tagu dev
w lokalnym repozytorium nie ma znaczenia; ten rodzaj push
, jako refspec, jest wypychaniem czystego usuwania.:remoteref
Pilot może, ale nie musi, pozwolić na usunięcie tagu (w zależności od dodanych dodatkowych haków). Jeśli pozwoli to na usunięcie, tag zniknie, a po git push --tags
chwili, gdy masz lokalny dev
znacznik wskazujący na jakiś obiekt repozytorium tagów zatwierdzonych lub z adnotacjami, wyślij nowy dev
tag. Na pilocie dev
będzie teraz nowo utworzony tag, więc pilot prawdopodobnie pozwoli na wypchnięcie (znowu zależy to od dodanych dodatkowych haków).
Pchnięcie siły jest prostsze. Jeśli chcesz mieć pewność, nie do niczego aktualizacji innych niż tagu, po prostu powiedz git push
naciskać tylko jeden refspec:
git push --force origin refs/tags/dev:refs/tags/dev
(uwaga: nie musisz tego robić, --tags
jeśli jawnie wypychasz tylko jeden tag ref-spec).
1 Oczywiście powodem tego wbudowanego punktu zaczepienia jest pomoc w egzekwowaniu zachowania, którego oczekują inni użytkownicy tego samego zdalnego repozytorium: gałęzie nie są przewijane, a tagi nie poruszają się. Jeśli naciskasz na siłę, powinieneś poinformować innych użytkowników, że to robisz, aby mogli to poprawić. Zwróć uwagę, że „tagi w ogóle się nie poruszają” zostało na nowo wymuszone przez Git 1.8.2; poprzednie wersje umożliwiały znacznikowi „przesuwanie do przodu” na wykresie zmian, podobnie jak w przypadku nazw gałęzi. Zobacz informacje o wydaniu git 1.8.2 .
2 To trywialne, jeśli możesz zalogować się na pilocie. Po prostu przejdź do repozytorium Git i uruchom git tag -d dev
. Zwróć uwagę, że w każdym przypadku - usuwając znacznik na pilocie lub używając go git push
do usunięcia - istnieje okres, w którym każdy, kto uzyska dostęp do pilota, stwierdzi, że dev
brakuje tagu. (Będą one nadal mają swój stary tag, jeśli już masz, a może nawet przesunąć swój stary tag z powrotem w górę, zanim będzie można wcisnąć nowy).