Какво е таг на git, Как да създадете тагове & Как да проверите отдалечен(и) таг(и) на git

когато проверявам отдалечен таг на git, използвам команда като тази:

git checkout -b local_branch_name origin/remote_tag_name

Получавам такава грешка:

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

Мога да намеря remote_tag_name, когато използвам командата git tag.

Решение

Нека започнем с обяснение на това какво е таг в git

Тагът се използва за обозначаване и маркиране на конкретен запис в историята.
Обикновено се използва за отбелязване на точките на издаване (напр. v1.0 и т.н.).

Въпреки че тагът може да изглежда подобен на клон, тагът обаче не се променя.
Той насочва директно към конкретен commit в историята.


Няма да можете да изтеглите таговете, ако те не са локално в хранилището ви, така че първо трябва да изтеглите таговете в локалното си хранилище.

На първо място се уверете, че тагът съществува локално, като направите

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

След това проверете тага, като стартирате

git checkout tags/ -b 

Вместо origin използвайте префикса tags/.


В тази извадка имате 2 тага версия 1.0 и версия 1.1, които можете да проверите с някое от следните действия:

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

Всички горепосочени действия ще бъдат еднакви, тъй като тагът е само указател към дадена ревизия.

произход: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Как да видите списъка с всички тагове?

# list all tags
git tag

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

Как да създаваме тагове?

Има 2 начина за създаване на таг:

# lightweight tag 
git tag 

# annotated tag
git tag -a

Разликата между двата начина е, че когато създавате анотиран таг, можете да добавяте метаданни, както при commit в git:
име, електронна поща, дата, коментар & подпис

Как да изтрием таговете?

# delete any given tag
git tag -d 

# Don't forget to remove the deleted tag form the server with push tags

Как да клонирате определен таг?

За да вземете съдържанието на даден таг, можете да използвате командата checkout.
Както беше обяснено по-горе, таговете са като всички останали коммисии, така че можем да използваме checkout и вместо да използваме SHA-1, просто да го заменим с името на тага

Вариант 1:

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

# checkout the specific tag
git checkout tags/ -b 

Вариант 2:

Използване на командата clone

Тъй като git поддържа плътен клонинг, чрез добавяне на --отклонение към командата clone можем да използваме името на тага вместо името на клона. Git знае как да "преведе" дадения SHA-1 към съответния commit

# Clone a specific tag name using git clone 
 git clone  --branch=

git clone --branch=

--branch може също така да приема тагове и да отделя HEAD при този commit в полученото хранилище.


Как да избутаме тагове?

git push --tags

За избутване на всички тагове:

git push --tags 

За изтласкване на анотирани тагове и тагове от текущата история на веригата използвайте::

git push --follow-tags

Този флаг --follow-tags изтласква както съобщения, така и само тагове, които са и двете:

  • Анотирани тагове (така че можете да пропуснете локалните/темп тагове за изграждане)
  • Тагове, до които може да се достигне (предшественик) от текущия клон (намиращи се в историята)

От версия 2.4 на Git можете да го зададете с помощта на конфигурацията

git config --global push.followTags true

Коментари (8)

(Написването на този отговор отне известно време, а отговорът на codeWizard's е правилен по цел и същност, но не е напълно завършен, така че все пак ще го публикувам.)

Няма такова нещо като "отдалечен таг на Git". Съществуват само "тагове". Изтъквам всичко това не за да бъда педантичен,1 а защото има голямо объркване по този въпрос сред обикновените потребители на Git, а документацията на Git не е много полезна2 за начинаещите. (Не е ясно дали объркването идва заради лошата документация, или лошата документация идва, защото това по своята същност е малко объркващо, или какво.) Съществуват "отдалечени клонове", по-правилно наричани "клонове за отдалечено проследяване", но си струва да се отбележи, че те всъщност са локални единици. Няма обаче отдалечени маркери (освен ако не ги измислите отново). Съществуват само локални тагове, така че трябва да получите локален таг, за да го използвате. Общата форма на имената за конкретни предавания - която Git нарича references - е всеки низ, започващ с refs/. Редица, започваща с refs/heads/, назовава клон; низ, започващ с refs/remotes/, назовава клон за отдалечено проследяване; а низ, започващ с refs/tags/, назовава таг. Името refs/stash е препратка към хранилището (както се използва от git stash; обърнете внимание на липсата на завършваща наклонена черта). Съществуват някои необичайни имена от специален тип, които не започват с refs/: HEAD, ORIG_HEAD, MERGE_HEAD и CHERRY_PICK_HEAD в частност са също имена, които могат да се отнасят до конкретни коммисии (въпреки че HEAD обикновено съдържа името на клона, т.е. съдържа ref: refs/heads/branch). Но по принцип препратките започват с refs/. Едно от нещата, които Git прави, за да направи това объркващо, е, че ви позволява да пропускате refs/, а често и думата след refs/. Например, можете да пропуснете refs/heads/ или refs/tags/, когато се позовавате на локален клон или таг - и всъщност задължително пропускате refs/heads/, когато проверявате локален клон! Можете да направите това винаги, когато резултатът е недвусмислен, или - както току-що отбелязахме - когато трябва да го направите (за git checkout branch*). Вярно е, че препратки съществуват не само в собственото ви хранилище, но и в отдалечени хранилища. Git обаче ви дава достъп до референциите на отдалечено хранилище'само в много специфични моменти: а именно по време на операциите fetch и push. Можете също така да използвате git ls-remote или git remote show, за да ги видите, но fetch и push са по-интересните точки на контакт.

Refspecs

По време на операциите fetch и push Git използва низове, които нарича refspecs, за да прехвърля референции между локалното и отдалеченото хранилище. По този начин, именно в тези моменти и чрез refspecs, две Git хранилища могат да се синхронизират помежду си. След като имената ви се синхронизират, можете да използвате същото име, което използва някой от отдалеченото. При fetch обаче има някаква специална магия, която засяга както имената на клоновете, така и имената на таговете. Трябва да мислите за git fetch като за насочване на вашия Git да извика (или може би да изпрати текстово съобщение) друг Git - "отдалечения" - и да проведе разговор с него. В началото на този разговор отдалеченият Git изброява всички свои препратки: всичко в refs/heads/ и всичко в refs/tags/, както и всички други препратки, които има. Вашият Git ги преглежда и (въз основа на обичайния fetch refspec) преименува техните клонове. Нека разгледаме обичайния refspec за отдалеченото устройство с име оригинал:

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

Този refspec инструктира вашия Git да вземе всяко име, съответстващо на refs/heads/*, т.е. всеки клон на отдалеченото, и да промени името му на refs/remotes/origin/*, т.е. да запази съвпадащата част, като промени името на клона (refs/heads/) на име на клон, проследяващ отдалеченото (refs/remotes/, по-конкретно refs/remotes/origin/). Именно чрез този refspec клоновете на origin'стават ваши клонове за отдалечено проследяване за отдалечения origin. Името на клона се превръща в име на клон за отдалечено проследяване, като се включва името на отдалеченото, в този случай origin. Знакът плюс + в началото на refspec задава флага "force", т.е. вашият клон за дистанционно проследяване ще бъде актуализиран, за да съвпадне с името на клона на отдалеченото'устройство, независимо от това какво е необходимо, за да съвпадне. (Без флага + актуализациите на клона се ограничават до "бързи промени", а актуализациите на таговете просто се игнорират от версия 1.8.2 на Git или подобна - преди това се прилагаха същите правила за бързи промени).

Етикети

Но какво да кажем за етикетите? За тях няма рефспект - поне не по подразбиране. Можете да зададете такъв, като в този случай формата на refspec зависи от вас; или можете да стартирате git fetch --tags. Използването на --tags води до добавяне на refs/tags/*:refs/tags/* към refspec, т.е., тя пренася всички тагове (но не актуализира вашия таг, ако вече имате таг с това име, независимо от това какво казва тагът на отдалеченото'устройство Редактиране, януари 2017 г.: от Git 2.10, тестването показва, че --tags принудително актуализира вашите тагове от отдалечените'тагове, все едно refspec гласи +refs/tags/*:refs/tags/*; това може да е разлика в поведението от по-ранна версия на Git). Обърнете внимание, че тук няма преименуване: ако отдалеченият оригинал има таг xyzzy, а вие нямате, и вие git fetch origin "refs/tags/*:refs/tags/*", ще получите refs/tags/xyzzy, добавен към вашето хранилище (сочещ към същия commit като на отдалечения). Ако използвате +refs/tags/*:refs/tags/*, вашият таг xyzzy, ако имате такъв, се заменя с този от оригинал. Това означава, че флагът за сила + на refspec означава "замени моята референция'със стойността, която моят Git получава от техния Git".

Автоматични тагове по време на извличане

По исторически причини,3 ако не използвате нито опцията --tags, нито опцията --no-tags, git fetch предприема специални действия. Спомнете си, че по-горе казахме, че отдалеченото устройство започва да показва на вашия локален Git всички свои препратки, независимо дали вашият локален Git иска да ги види или не.4 Вашият Git отбелязва всички тагове, които вижда в този момент. След това, когато започне да изтегля всички обекти на предавания, от които се нуждае, за да обработва това, което извлича, ако някое от тези предавания има същия идентификатор като някой от тези тагове, git ще добави този таг - или тези тагове, ако няколко тага имат този идентификатор - към вашето хранилище. Редактиране, януари 2017 г.: тестването показва, че поведението в Git 2.10 вече е такова: Ако техният Git предоставя таг с име T, и вие нямате таг с име T, и идентификаторът на предаването, свързан с T, е родоначалник на един от техните клонове, които вашият git fetch разглежда, вашият Git добавя T към вашите тагове със или без --tags. Добавянето на --tags кара вашия Git да получи всичките им тагове, а също и да наложи актуализация.

В крайна сметка

Може да се наложи да използвате git fetch --tags, за да получите техните тагове. Ако имената на таговете им са в конфликт с имената на съществуващите тагове, може да се наложи (в зависимост от версията на Git) дори да изтриете (или да преименувате) някои от таговете си и след това да стартирате git fetch --tags, за да получите техните тагове. Тъй като таговете - за разлика от отдалечените клонове - нямат автоматично преименуване, имената на вашите тагове трябва да съвпадат с имената на техните тагове, поради което можете да имате проблеми с конфликти. В повечето нормални случаи обаче един обикновен git fetch ще свърши работа, като прехвърли техните коммити и съответстващите им тагове, и тъй като те - които и да са те - ще маркират коммитите в момента на публикуването им, вие ще сте в крак с техните тагове. Ако не създавате свои собствени тагове, нито смесвате тяхното хранилище с други хранилища (чрез множество отдалечени устройства), няма да има и колизии в имената на таговете, така че няма да ви се налага да се занимавате с изтриване или преименуване на тагове, за да получите техните тагове.

Когато ви трябват квалифицирани имена

По-горе споменах, че можете да пропускате refs/ почти винаги, а refs/heads/ и refs/tags/ и т.н. през повечето време. Но кога не можете? Пълният (или почти пълният) отговор се намира в документацията на gitrevisions. Git ще преобразува името в идентификатор на ревизия, като използва последователността от шест стъпки, посочена в линка. Любопитно е, че таговете имат предимство пред клоновете: ако има таг xyzzy и клон xyzzy и те сочат към различни коммити, тогава:

git rev-parse xyzzy

ще ви даде идентификатора, към който сочи тагът. Обаче - и това е нещото, което липсва в gitrevisions - git checkout предпочита имената на клоновете, така че git checkout xyzzy ще ви постави на клона, без да се съобразява с тага. В случай на двусмислие почти винаги можете да изпишете името на реферата, като използвате пълното му име, refs/heads/xyzzy или refs/tags/xyzzy. (Имайте предвид, че това работи с git checkout, но по може би неочакван начин: git checkout refs/heads/xyzzy предизвиква проверка на отделен глава, а не проверка на клон. Ето защо просто трябва да отбележите, че git checkout ще използва първо краткото име като име на клона: така'ще проверите клона xyzzy, дори ако тагът xyzzy съществува. Ако искате да проверите тага, можете да използвате refs/tags/xyzzy.) Тъй като (както отбелязва gitrevisions) Git ще опита refs/name, можете също така просто да напишете tags/xyzzy, за да идентифицирате предаването с етикет xyzzy. (Ако обаче някой е успял да запише валидна референция с име xyzzy в $GIT_DIR, това ще се разреши като $GIT_DIR/xyzzy. Обикновено обаче в $GIT_DIR трябва да има само различните имена *HEAD.)

1Добре, добре, "не само за да бъда педантичен". :-) 2Някой би казал "много не-полезно", и всъщност съм склонен да се съглася. 3По принцип, git fetch и цялата концепция за отдалечени обекти и refspecs беше малко късно допълнение към Git, което се появи около времето на Git 1.5. Преди това имаше само някои специални случаи ad-hoc и tag-fetching беше един от тях, така че беше включен чрез специален код. 4Ако ви помогне, мислете за отдалечения Git като за flasher, в жаргонен смисъл.

Коментари (2)

За да получите специфичния код на етикета, опитайте се да създадете нов клон, добавете кода на етикета в него. Направих го с командата : $git checkout -b newBranchName tagName

Коментари (0)