(Для написания этого ответа потребовалось некоторое время, и ответ 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 checkout A, что такоеA? Как вы создалиA?