Co to jest git tag, jak tworzyć tagi i jak kasować zdalne tagi git

522

kiedy kasuję zdalny tag git użyj polecenia takiego jak to:

git checkout -b local_branch_name origin/remote_tag_name

Mam taki błąd:

error: pathspec `origin/remote_tag_name` did not match any file(s) known to git.

Mogę znaleźć nazwę nazwa_zdalnego tagu, gdy używam polecenia git tag.

Ryanqy
źródło

Odpowiedzi:

1152

Zacznijmy od wyjaśnienia, czym jest tag w git

wprowadź opis zdjęcia tutaj

Tag służy do oznaczania i oznaczania konkretnego zatwierdzenia w historii.
Zwykle służy do oznaczania punktów uwalniania (np. V1.0 itp.).

Chociaż tag może wyglądać podobnie do gałęzi, nie zmienia się . Wskazuje bezpośrednio na konkretne zatwierdzenie w historii.

wprowadź opis zdjęcia tutaj


Nie będzie można wyewidencjonować tagów, jeśli nie są one lokalnie w twoim repozytorium, więc najpierw musisz przejść do fetchtagów do lokalnego repozytorium.

Po pierwsze, upewnij się, że tag istnieje lokalnie, wykonując

# --all will fetch all the remotes.
# --tags will fetch all tags as well
$ git fetch --all --tags --prune

Następnie sprawdź tag, uruchamiając

$ git checkout tags/<tag_name> -b <branch_name>

Zamiast originużywać tags/przedrostka.


W tym przykładzie masz 2 tagi w wersji 1.0 i wersji 1.1, możesz je sprawdzić za pomocą jednego z poniższych:

$ git checkout A  ...
$ git checkout version 1.0  ...
$ git checkout tags/version 1.0  ...

Wszystkie powyższe zrobią to samo, ponieważ znacznik jest tylko wskaźnikiem do danego zatwierdzenia.

wprowadź opis zdjęcia tutaj
pochodzenie: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Jak wyświetlić listę wszystkich tagów?

# list all tags
$ git tag

# list all tags with given pattern ex: v-
$ git tag --list 'v-*'

Jak tworzyć tagi?

Istnieją 2 sposoby utworzenia tagu:

# lightweight tag 
$ git tag 

# annotated tag
$ git tag -a

Różnica między nimi polega na tym, że podczas tworzenia znacznika z adnotacjami można dodawać metadane w git commit:
imię, adres e-mail, datę, komentarz i podpis

wprowadź opis zdjęcia tutaj

Jak usunąć tagi?

# delete any (local) given tag
$ git tag -d <tag name>

# Delete a tag from the server with push tags
$ git push --delete origin <tag name>

Jak sklonować określony tag?

Aby pobrać zawartość danego znacznika, możesz użyć checkoutpolecenia. Jak wyjaśniono powyżej, tagi są jak wszelkie inne zatwierdzenia, więc możemy używać checkouti zamiast używać SHA-1, po prostu zastępując go tag_name

Opcja 1:

# Update the local git repo with the latest tags from all remotes
$ git fetch --all

# checkout the specific tag
$ git checkout tags/<tag> -b <branch>

Opcja 2:

Za pomocą polecenia klonowania

Ponieważ git obsługuje płytkie klonowanie poprzez dodanie polecenia --branchdo klonowania, możemy użyć nazwy znacznika zamiast nazwy gałęzi. Git wie, jak „przetłumaczyć” dany SHA-1 na odpowiedni zatwierdzenie

# Clone a specific tag name using git clone 
$ git clone <url> --branch=<tag_name>

git clone --branch =

--branch może również pobierać tagi i odłącza HEAD przy tym zatwierdzeniu w wynikowym repozytorium.


Jak przesuwać tagi?

git push --tags

Aby wypchnąć wszystkie tagi:

# Push all tags
$ git push --tags 

Używanie refs/tagszamiast tylko określenia <tagname>.

Dlaczego? - Zaleca się używać, refs/tagsponieważ czasami tagi mogą mieć taką samą nazwę jak twoje gałęzie, a zwykłe git push popchnie gałąź zamiast tag

Aby przesłać tagi z adnotacjami i bieżące tagi łańcucha historii, użyj:

git push --follow-tags

Ta flaga --follow-tagswypycha zarówno zatwierdzenia, jak i tylko tagi, które są jednocześnie:

  • Tagi z adnotacjami (dzięki czemu można pominąć tagi budowania lokalnego / tymczasowego)
  • Osiągalne znaczniki (przodek) z bieżącej gałęzi (znajdujące się w historii)

wprowadź opis zdjęcia tutaj

W Git 2.4 możesz to ustawić za pomocą konfiguracji

$ git config --global push.followTags true

Ściągawka: wprowadź opis zdjęcia tutaj


CodeWizard
źródło
3
miły. git checkout A. co jest A? Jak stworzyłeś A?
Kochanie,
3
@CodeWizard Nice schemat blokowy! Jakiego oprogramowania użyłeś do jego wytworzenia?
Giovanni Lovato
4
@Honey Ajest hashem zatwierdzającym
Alex Baklanov
2
@GiovanniLovato Schemat blokowy jest schematem strony trzeciej. Link do obrazu to backlog.com/git-tutorial/img/post/stepup/…, który znajduje się na tej stronie backlog.com/git-tutorial/stepup/stepup4_1.html strony o nazwie Git Beginner's Guide for Dummies (zaległości .com).
George
2
Warto zauważyć, że git checkout tags/<tag_name> -b <branch_name>wymaga -b <branch_name>. git checkout tags/<tag_name>obdarzył mnie oderwaną głową. Zgodnie z tym artykułem na temat odłączonej głowy , unikniesz odłączonej głowy, tymczasowo tworząc i usuwając gałąź. To dość obcy proces pracy. Oczywiście jako użytkownik git muszę przyzwyczaić się do tworzenia i usuwania oddziałów dla zabawy i zysków.
icc97
194

( Napisanie tej odpowiedzi zajęło trochę czasu, a odpowiedź CodeWizard jest poprawna pod względem celu i istoty, ale nie do końca pełna, więc i tak to opublikuję.)


Nie ma czegoś takiego jak „zdalny tag Git”. Są tylko „tagi”. Zwracam uwagę na to, aby nie być pedantycznym 1, ale ponieważ istnieje wiele zamieszania na ten temat z przypadkowymi użytkownikami Git, a dokumentacja Git nie jest zbyt pomocna 2 dla początkujących. (Nie jest jasne, czy zamieszanie nastąpiło z powodu złej dokumentacji, czy też złej dokumentacji, ponieważ z natury jest to nieco mylące, czy co.)

Nie „zdalne oddziały”, bardziej poprawnie nazywane „zdalne śledzenie oddziałów”, ale warto zauważyć, że są to w rzeczywistości podmioty lokalne. Nie ma jednak zdalnych tagów (chyba że je wymyślisz). Są tylko tagi lokalne, więc musisz go pobrać lokalnie, aby go użyć.

Ogólna forma nazw dla konkretnych zatwierdzeń - do których odwołuje się Git - to dowolny ciąg zaczynający się od refs/. Ciąg rozpoczynający się od refs/heads/nazwy gałęzi; ciąg rozpoczynający się od refs/remotes/nazwy gałęzi zdalnego śledzenia; oraz ciąg rozpoczynający się od refs/tags/nazwy znacznika. Nazwa refs/stashjest odniesieniem do skrytki (w znaczeniu używanym przez git stash; zwróć uwagę na brak ukośnika końcowego).

Istnieją pewne nietypowe imiona specjalnym etui, które nie zaczynają się refs/: HEAD, ORIG_HEAD, MERGE_HEAD, a CHERRY_PICK_HEADw szczególności są również nazwy, które mogą odnosić się do konkretnych zatwierdzeń (choć HEADzazwyczaj zawiera nazwę oddziału, czyli zawiera ). Ale ogólnie odniesienia zaczynają się od .ref: refs/heads/branchrefs/

Jedną z rzeczy, które Git robi, aby wprowadzić to w błąd, jest to, że pozwala ci to pominąć refs/i często słowo po refs/. Na przykład możesz pominąć refs/heads/lub refs/tags/odnosząc się do lokalnego oddziału lub tagu - i faktycznie musisz go pominąć refs/heads/podczas sprawdzania lokalnego oddziału! Możesz to zrobić, gdy wynik jest jednoznaczny, lub - jak właśnie zauważyliśmy - kiedy musisz to zrobić (dla ).git checkout branch

To prawda, że ​​referencje istnieją nie tylko w twoim własnym repozytorium, ale także w zdalnych repozytoriach. Jednak Git daje dostęp do referencji zdalnego repozytorium tylko w bardzo określonych momentach: mianowicie podczas fetchi pushoperacji. Można również użyć git ls-remotelub git remote showje zobaczyć, ale fetchi pushsą bardziej interesujące punkty styku.

Refspecs

Podczas fetchi pushGit używa ciągów, które wywołuje refspecs do przesyłania referencji między lokalnym a zdalnym repozytorium. Tak więc w tych czasach i poprzez refspecs dwa repozytoria Git mogą się zsynchronizować. Gdy twoje imiona zostaną zsynchronizowane, możesz użyć tego samego imienia, którego używa osoba z pilotem. Jest tu jednak trochę magii fetch, która wpływa zarówno na nazwy oddziałów, jak i nazwy znaczników.

Powinieneś pomyśleć o poleceniu git fetchGitowi wywołania (lub wiadomości tekstowej) innego Gita - „zdalnego” - i przeprowadzenia z nim rozmowy. Na początku tej rozmowy pilot wyświetla wszystkie swoje odniesienia: wszystko wewnątrz refs/heads/i wszystko w środku refs/tags/, wraz z wszelkimi innymi odniesieniami, które posiada. Twój Git skanuje je i (na podstawie zwykłego refspecu pobierania) zmienia nazwy swoich gałęzi.

Rzućmy okiem na normalny refspec dla pilota o nazwie origin:

$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$ 

Ten refspec instruuje Gita, aby pobierał każdą pasującą nazwę - refs/heads/*tj. Każdą gałąź na pilocie - i zmieniał jej nazwę na refs/remotes/origin/*, tj. Utrzymywał tę samą dopasowaną część, zmieniając nazwę gałęzi ( refs/heads/) na nazwę gałęzi zdalnego śledzenia ( refs/remotes/w szczególności , refs/remotes/origin/).

To dzięki tej refspec że origin„s oddziały stają się twoje gałęzie zdalnego śledzenia do zdalnego origin. Nazwa oddziału staje się nazwą oddziału śledzącego zdalnie, wraz z nazwą pilota, w tym przypadku originzawartą. Znak plus +z przodu refspec ustawia flagę „force”, tzn. Gałąź zdalnego śledzenia zostanie zaktualizowana, aby pasowała do nazwy gałęzi pilota, niezależnie od tego, co trzeba zrobić, aby dopasować. (Bez tego +aktualizacje oddziałów są ograniczone do zmian „szybkiego przewijania do przodu”, a aktualizacje znaczników są po prostu ignorowane od wersji Git 1.8.2 lub wcześniej - wcześniej stosowane były te same reguły szybkiego przewijania).

Tagi

Ale co z tagami? Nie ma dla nich żadnego odniesienia - przynajmniej domyślnie. Możesz ustawić jeden, w którym to przypadku forma refspec zależy od Ciebie; lub możesz biegać git fetch --tags. Korzystanie --tagsskutkuje dodaniem refs/tags/*:refs/tags/*do refspec, czyli przynosi nad wszystkimi znacznikami ( ale nie aktualizuje swój znacznik jeśli masz już tag z tą nazwą, niezależnie od tego, co tag zdalnego mówi Edit sty 2017: jak Git 2.10 , testy pokazują, że --tagssiłą aktualizuje tagi z tagów pilota, tak jakby czytał refspec +refs/tags/*:refs/tags/*; może to różnić się w zachowaniu od wcześniejszej wersji Git).

Zauważ, że nie ma tutaj zmiany nazwy: jeśli pilot originma tag xyzzy, a ty nie, a ty git fetch origin "refs/tags/*:refs/tags/*"zostaniesz refs/tags/xyzzydodany do repozytorium (wskazując na to samo zatwierdzenie, co na pilocie). Jeśli go użyjesz, +refs/tags/*:refs/tags/*Twój tag xyzzy, jeśli go masz, zostanie zastąpiony tym z origin. Oznacza to, że +flaga siły na refspec oznacza „zastąp wartość mojej referencji tą, którą mój Git otrzymuje z Git”.

Automagiczne tagi podczas pobierania

Ze względów historycznych 3, jeśli nie użyjesz ani --tagsopcji, ani --no-tagsopcji, git fetchpodejmuje specjalne działania. Pamiętaj, że powiedzieliśmy powyżej, że pilot zaczyna się od wyświetlania w lokalnym Git wszystkich swoich referencji, niezależnie od tego, czy lokalny Git chce je zobaczyć, czy nie. 4 Twój Git bierze pod uwagę wszystkie tagi, które widzi w tym momencie. Następnie, gdy zacznie pobierać dowolne obiekty zatwierdzania, których potrzebuje, aby obsłużyć wszystko, co jest pobierane, jeśli jeden z tych zatwierdzeń ma taki sam identyfikator, jak dowolny z tych znaczników, git doda ten znacznik - lub te znaczniki, jeśli wiele znaczników ma ten identyfikator - do twoje repozytorium.

Edytuj, styczeń 2017 r .: testowanie pokazuje, że zachowanie w Git 2.10 jest teraz: Jeśli ich Git zapewnia znacznik o nazwie T , a ty nie masz znacznika o nazwie T , a identyfikator zatwierdzenia powiązany z T jest przodkiem jednej z jego gałęzi że Twój git fetchbada, Twój Git dodaje T do tagów z lub bez --tags. Dodanie --tagspowoduje, że Twój Git otrzymuje wszystkie swoje tagi, a także wymusza aktualizację.

Dolna linia

Być może będziesz musiał użyć git fetch --tagsich, aby uzyskać ich tagi. Jeśli ich nazwy znaczników konflikt z istniejącymi nazwami znaczników, to może (w zależności od wersji Git) nawet usunąć (lub zmienić nazwę) niektóre z tagów, a następnie uruchomić git fetch --tags, aby uzyskać ich tagi. Ponieważ znaczniki - w przeciwieństwie do zdalnych gałęzi - nie mają automatycznej zmiany nazwy, nazwy znaczników muszą odpowiadać ich nazwom, dlatego możesz mieć problemy z konfliktami.

Jednak w większości normalnych przypadków prosty git fetchwykona zadanie, przynosząc swoje zatwierdzenia i odpowiadające im znaczniki, a ponieważ oni - kimkolwiek są - będą oznaczać zatwierdzenia w momencie ich publikowania, będziesz nadążał za ich znacznikami. Jeśli nie utworzysz własnych tagów ani nie wymieszasz ich repozytorium z innymi repozytoriami (za pomocą wielu pilotów), nie będziesz mieć żadnych kolizji nazw tagów, więc nie będziesz musiał się martwić usuwaniem lub zmianą nazw tagów uzyskać ich tagi.

Kiedy potrzebujesz kwalifikowanych nazwisk

Wspomniałem wyżej, że można pominąć refs/prawie zawsze, i refs/heads/a refs/tags/i tak na większość czasu. Ale kiedy nie możesz?

Kompletny (lub prawie pełna tak) Odpowiedź jest w tej gitrevisionsdokumentacji . Git rozpozna nazwę do identyfikatora zatwierdzenia, korzystając z sześcioetapowej sekwencji podanej w łączu. Co ciekawe, znaczniki zastępują gałęzie: jeśli istnieje znacznik xyzzyi gałąź xyzzyi wskazują one różne zatwierdzenia, to:

git rev-parse xyzzy

poda ci identyfikator, na który wskazuje tag. Jednak - i tego właśnie brakuje gitrevisions- git checkoutpreferuje nazwy gałęzi, więc git checkout xyzzyumieści cię w gałęzi, ignorując tag.

W przypadku niejasności prawie zawsze możesz przeliterować nazwę ref, używając jej pełnej nazwy refs/heads/xyzzylub refs/tags/xyzzy. (Należy pamiętać, że to czyni pracę z git checkout, ale w może nieoczekiwany sposób: git checkout refs/heads/xyzzypowoduje kasę wolnostojący-Head zamiast kasie oddziału To dlatego po prostu trzeba pamiętać, że. git checkoutBędzie używać nazwy skróconej jako nazwa oddziału pierwsze: to, w jaki sposób sprawdź gałąź, xyzzynawet jeśli tag xyzzyistnieje. Jeśli chcesz sprawdzić tag, możesz użyć refs/tags/xyzzy).

Ponieważ (jak gitrevisionszauważa) Git spróbuje , możesz po prostu napisać, aby zidentyfikować zatwierdzony tag . (Jeśli ktoś udało się napisać poprawny nazwie odniesienie do , jednakże będzie to rozwiązać jak . Ale zazwyczaj tylko różne nazwy powinny być ).refs/nametags/xyzzyxyzzyxyzzy$GIT_DIR$GIT_DIR/xyzzy*HEAD$GIT_DIR


1 Dobra, dobra, „nie tylko być pedantycznym”. :-)

2 Niektórzy powiedzieliby „bardzo nieużyteczni”, a ja raczej raczej się zgadzam.

3 Zasadniczo git fetchi cała koncepcja pilotów i referencji była nieco późnym dodatkiem do Git, działającym w czasach Gita 1.5. Wcześniej istniały tylko specjalne przypadki ad-hoc, a pobieranie tagów było jednym z nich, więc zostało wprowadzone w życie za pomocą specjalnego kodu.

4 Jeśli to pomoże, pomyśl o zdalnym Gicie jako flasherze w znaczeniu slangu.

Trek
źródło
Świetny opis. Jedna mała nitka: git fetchpobierze tylko tagi pilota, biorąc pod uwagę --tagsarg.
tydzień
@cweekly: zachowanie --tags, --no-tagsi domyślnie jest całkiem trudne. Domyślnie wprowadzane są tagi, których nie masz, a które są w zatwierdzonych przez Ciebie zmianach (zobacz edycję z stycznia 2017 r.) Ale są tu również usterki, a współczesny Git ma swoje --tagi / --no-tag obsługuje kod jeszcze raz poprawiony, co prawdopodobnie doprowadzi do jeszcze bardziej specjalnych przypadków narożnych.
trek
1

Aby pobrać tag git, należy wykonać następujące polecenie

git checkout tags/tag-name -b branch-name

np. jak wspomniano poniżej.

 git checkout tags/v1.0 -b v1.0-branch

Aby pobrać wszystkie tagi, użyj polecenia

git fetch --all --tags
mani
źródło
0

Aby uzyskać konkretny kod tagu, spróbuj utworzyć nowy oddział i dodaj kod tagu. Zrobiłem to z polecenia:$git checkout -b newBranchName tagName

Rahul Khatri
źródło