Что такое тег git, как создавать теги и как оформить заказ удаленного тега (ов) git

524

когда я извлекаю команду git tag, используйте следующую команду:

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.

Я могу найти имя_удаленного_запуска, когда использую команду git tag.

Ryanqy
источник

Ответы:

1154

Давайте начнем с объяснения, что такое тег в git

введите описание изображения здесь

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

Хотя тег может выглядеть как ветвь, тег, однако, не меняется . Это указывает непосредственно на конкретный коммит в истории.

введите описание изображения здесь


Вы не сможете извлекать теги, если они не находятся локально в вашем хранилище, поэтому сначала вам нужно fetchпривязать теги к своему локальному хранилищу.

Сначала убедитесь, что тег существует локально, выполнив

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

Затем проверьте тег, запустив

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

Вместо того, чтобы 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

Разница между этими двумя заключается в том, что при создании аннотированного тега вы можете добавлять метаданные, как в коммите git:
имя, электронная почта, дата, комментарий и подпись.

введите описание изображения здесь

Как удалить теги?

# 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>

Как клонировать определенный тег?

Чтобы получить содержимое данного тега, вы можете использовать checkoutкоманду. Как объяснено выше, теги похожи на любые другие коммиты, поэтому мы можем использовать их checkoutвместо SHA-1, просто заменив их на tag_name

Опция 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>

Вариант 2:

Использование команды клона

Так как git поддерживает мелкое клонирование , добавляя --branchк команде clone, мы можем использовать имя тега вместо имени ветви. Git знает, как «перевести» данный SHA-1 в соответствующий коммит

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

git clone --branch =

--branch может также взять теги и отсоединить HEAD при этом коммите в результирующем репозитории.


Как нажать метки?

git push --tags

Чтобы нажать все теги:

# Push all tags
$ git push --tags 

Использование refs/tagsвместо того, чтобы просто указать <tagname>.

Почему? - Рекомендуется использовать, refs/tagsтак как иногда теги могут иметь то же имя, что и ваши ветви, и простой git push будет выдвигать ветку вместо тега.

Для добавления аннотированных тегов и текущих тегов истории используйте:

git push --follow-tags

Этот флаг --follow-tagsвыдвигает как коммиты, так и только теги , которые оба:

  • Аннотированные теги (так что вы можете пропустить локальные / временные теги сборки)
  • Доступные теги (предок) из текущей ветви (расположенной в истории)

введите описание изображения здесь

Из Git 2.4 вы можете установить его, используя конфигурацию

$ git config --global push.followTags true

Cheatsheet: введите описание изображения здесь


CodeWizard
источник
3
отлично. git checkout A, что такое A? Как вы создали A?
Мед
3
@CodeWizard Хорошая блок-схема! Какое программное обеспечение вы использовали для его производства?
Джованни Ловато,
4
@Мед A- хеш коммита
Алекс Бакланов
2
@GiovanniLovato Блок-схема является сторонней. Ссылка на изображение - backlog.com/git-tutorial/img/post/stepup/…, которая находится на этой странице backlog.com/git-tutorial/stepup/stepup4_1.html веб-сайта под названием Git Beginner's Guide для чайников (backlog .com).
Джордж
2
Стоит отметить, что git checkout tags/<tag_name> -b <branch_name>требует -b <branch_name>. git checkout tags/<tag_name>дал мне отстраненную голову. Согласно этой статье об отделенной головке , вы избегаете отсоединенной головки, временно создавая и удаляя ветку. Это довольно инопланетный рабочий процесс. Я, как пользователь git, должен привыкнуть к созданию и удалению веток для удовольствия и получения прибыли.
icc97
194

(Для написания этого ответа потребовалось некоторое время, и ответ CodeWizard верен по своей цели и сути, но не полностью, поэтому я все равно опубликую это.)


Не существует такого понятия, как «удаленный тег Git». Есть только «теги». Я указываю все это не быть педантичным, 1 , а потому что есть большая путаница по этому поводу со случайными пользователями Git, и документация Git не очень полезно 2 для начинающих. (Непонятно, возникает ли путаница из-за плохой документации или плохой документации из-за того, что это несколько смущает, или как.)

Там есть «удаленные ветви», более правильно называют «дистанционное отслеживание ветвей», но стоит отметить , что это на самом деле местные организации. Тем не менее, нет никаких удаленных тегов (если только вы не изобретаете их). Есть только локальные теги, поэтому вам нужно получить тег локально, чтобы использовать его.

Общая форма имен для конкретных коммитов, которые Git называет ссылками, - это любая строка, начинающаяся с refs/. Строка, которая начинается с refs/heads/имен ветки; строка, начинающаяся с refs/remotes/имен ветки удаленного отслеживания; и строка, начинающаяся с refs/tags/имен тега. Имя refs/stashявляется ссылкой на тайник (используется git stash; обратите внимание на отсутствие косой черты).

Есть некоторые необычные имена для особых случаев , которые не начинаются с refs/: HEAD, ORIG_HEAD, MERGE_HEAD, и , CHERRY_PICK_HEADв частности , все также имена , которые могут относиться к конкретным фиксациям (хотя HEADобычно содержит название филиала, то есть содержит ). Но в целом ссылки начинаются с .ref: refs/heads/branchrefs/

Единственное, что 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и pushGit использует строки, которые он вызывает refspecs, для передачи ссылок между локальным и удаленным репозиторием. Таким образом, именно в это время и с помощью refspecs два репозитория Git могут синхронизироваться друг с другом. Как только ваши имена синхронизируются, вы можете использовать то же имя, которое использует кто-то с удаленного компьютера. Здесь есть некоторая особая магия fetch, которая влияет как на имена веток, так и на имена тегов.

Вы должны думать о том, чтобы git fetchнаправить ваш Git на вызов (или, возможно, текстовое сообщение) другого Git - «удаленного» - и поговорить с ним. В начале этого разговора пульт дистанционного управления перечисляет все его ссылки: все в нем refs/heads/и все в нем refs/tags/, а также любые другие ссылки, которые он имеет. Ваш Git просматривает их и (на основе обычного refspec fetch) переименовывает их ветви.

Давайте посмотрим на нормальный refspec для пульта с именем origin:

$ 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ветви «S стать вашими дистанционного отслеживания ветвей для удаленного origin. Имя ветви становится именем ветви удаленного отслеживания, в том числе и имя удаленного origin. Знак «плюс» +в начале refspec устанавливает флаг «force», т. Е. Ветка удаленного отслеживания будет обновлена ​​в соответствии с именем ветки удаленного сервера, независимо от того, что требуется для его сопоставления. (Без этого +обновления веток ограничиваются изменениями «ускоренной перемотки», а обновления тегов просто игнорируются начиная с Git версии 1.8.2 или около того - до этого применялись те же правила ускоренной перемотки.)

Теги

Но как насчет тегов? Там нет refspec для них - по крайней мере, не по умолчанию. Вы можете установить один, в этом случае форма refspec зависит от вас; или ты можешь бежать git fetch --tags. Использование --tagsприводит к добавлению refs/tags/*:refs/tags/*в refspec, т. Е. Переносит все теги ( но не обновляет ваш тег, если у вас уже есть тег с таким именем, независимо от того, что говорит тег удаленного устройства Edit, Jan 2017: начиная с Git 2.10 тестирование показывает, что --tagsпринудительно обновляет ваши теги из тегов пульта, как если бы refspec читал +refs/tags/*:refs/tags/*; это может отличаться по поведению от более ранней версии Git).

Обратите внимание, что здесь нет переименования: если у пульта originесть тег xyzzy, и у вас нет, и у вас git fetch origin "refs/tags/*:refs/tags/*", вы refs/tags/xyzzyдобавлены в свой репозиторий (указывая на тот же коммит, что и на удаленном). Если вы используете, +refs/tags/*:refs/tags/*то ваш тег xyzzy, если он у вас есть, заменяется на тег из origin. То есть +флаг force в refspec означает «заменить значение моей ссылки на значение, которое мой Git получает из их Git».

Автоматические метки во время выборки

По историческим причинам 3, если вы не используете ни --tagsопцию, ни --no-tagsопцию, git fetchпредпринимает специальные действия. Помните, что мы говорили выше, что удаленный компьютер начинает с отображения в вашем локальном Git всех своих ссылок, хочет ли ваш локальный Git их видеть или нет. 4 Ваш Git принимает к сведению все теги, которые он видит на данный момент. Затем, когда он начинает загружать любые объекты коммитов, которые ему нужны для обработки того, что он выбирает, если один из этих коммитов имеет тот же ID, что и любой из этих тегов, 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/nametags/xyzzyxyzzyxyzzy$GIT_DIR$GIT_DIR/xyzzy*HEAD$GIT_DIR


+1 Ладно, ладно, «не просто быть педантичным». :-)

2 Кто-то скажет «очень бесполезно», и я бы согласился на самом деле.

3 По сути, git fetchи вся концепция удаленных и refspecs была немного поздним дополнением к Git, появившимся во времена Git 1.5. До этого было только несколько специальных особых случаев, и выборка тегов была одной из них, поэтому она была обнаружена с помощью специального кода.

4 Если это поможет, подумайте об удаленном Git как о мигалке в сленге.

Торек
источник
Отличная рецензия. Одна крошечная гнида: git fetchбудет получать только теги пульта дистанционного управления с указанным --tagsаргументом.
еженедельно
@cweekly: поведение --tags, --no-tagsи по умолчанию на самом деле довольно сложно. По умолчанию вводятся те теги, которых у вас нет, которые содержатся в коммитах, которые вы вносите. (См. Редактирование за январь 2017 г.) Но и здесь есть глюки, и у современного Git есть свои --tags / Код обработки --no-tags снова пересмотрен, что, вероятно, приведет к еще более особым случаям.
Торек
1

Чтобы извлечь тег git, вы должны выполнить следующую команду

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

например, как указано ниже.

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

Чтобы получить все теги, используйте команду

git fetch --all --tags
мани
источник
0

Чтобы получить конкретный код тега, попробуйте создать новую ветку, добавьте в нее код тега. Я сделал это по команде:$git checkout -b newBranchName tagName

Рахул Хатри
источник