Давайте начнем с объяснения, что такое тег в 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:
git checkout A
, что такоеA
? Как вы создалиA
?A
- хеш коммитаgit checkout tags/<tag_name> -b <branch_name>
требует-b <branch_name>
.git checkout tags/<tag_name>
дал мне отстраненную голову. Согласно этой статье об отделенной головке , вы избегаете отсоединенной головки, временно создавая и удаляя ветку. Это довольно инопланетный рабочий процесс. Я, как пользователь git, должен привыкнуть к созданию и удалению веток для удовольствия и получения прибыли.(Для написания этого ответа потребовалось некоторое время, и ответ 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/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 - «удаленного» - и поговорить с ним. В начале этого разговора пульт дистанционного управления перечисляет все его ссылки: все в немrefs/heads/
и все в немrefs/tags/
, а также любые другие ссылки, которые он имеет. Ваш Git просматривает их и (на основе обычного refspec fetch) переименовывает их ветви.Давайте посмотрим на нормальный refspec для пульта с именем
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
, и они указывают на разные коммиты, то:даст вам идентификатор, на который указывает тег. Однако - а это то, чего не хватает
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
*HEAD
$GIT_DIR
+1 Ладно, ладно, «не просто быть педантичным». :-)
2 Кто-то скажет «очень бесполезно», и я бы согласился на самом деле.
3 По сути,
git fetch
и вся концепция удаленных и refspecs была немного поздним дополнением к Git, появившимся во времена Git 1.5. До этого было только несколько специальных особых случаев, и выборка тегов была одной из них, поэтому она была обнаружена с помощью специального кода.4 Если это поможет, подумайте об удаленном Git как о мигалке в сленге.
источник
git fetch
будет получать только теги пульта дистанционного управления с указанным--tags
аргументом.--tags
,--no-tags
и по умолчанию на самом деле довольно сложно. По умолчанию вводятся те теги, которых у вас нет, которые содержатся в коммитах, которые вы вносите. (См. Редактирование за январь 2017 г.) Но и здесь есть глюки, и у современного Git есть свои --tags / Код обработки --no-tags снова пересмотрен, что, вероятно, приведет к еще более особым случаям.Чтобы извлечь тег git, вы должны выполнить следующую команду
например, как указано ниже.
Чтобы получить все теги, используйте команду
источник
Чтобы получить конкретный код тега, попробуйте создать новую ветку, добавьте в нее код тега. Я сделал это по команде:
$git checkout -b newBranchName tagName
источник