Как исправить «предупреждение: символ c ссылка висит» в git - PullRequest
0 голосов
/ 06 февраля 2020

Недавно я начал замечать, что в одном из моих git репозиториев при выполнении любой команды git я получаю следующее предупреждение:

warning: symbolic ref is dangling: refs/remotes/origin/HEAD

Что это значит и как мне это исправить?

1 Ответ

2 голосов
/ 06 февраля 2020

Как это исправить

Поскольку этот конкретный символ c ref в любом случае бесполезен, я рекомендую просто удалить его:

git remote set-head origin --delete

Если вам нравится этот бесполезный символ c ref, вместо этого вы можете Git автоматически обновить его:

git remote set-head origin --auto

Это заставит ваш Git вызвать другой Git на origin, спросить, какой у него текущий ответвляется сейчас , и соответственно обновите ваш символ c -ref origin/HEAD.

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

О ссылках

Давайте начнем отмечая, что такое ref :

  • Ссылка или ссылка - это имя. У имени есть некоторые ограничения (см. git check-ref-format документацию , но в основном это просто строка букв и цифр и т. Д., Как мы можем надеяться, произнесение имени, которое что-то значит для вас.

    Например, имя ветви - это ссылка. Так же как и имя тега.

  • Большинство этих имен на самом деле начинаются с refs/. Единственные, которые не Они не всегда называются refs (Git не совсем соответствует этому): это специальные имена HEAD, ORIG_HEAD, CHERRY_PICK_HEAD и т. д. (Они все либо HEAD, что является самым особенным из всех, либо оканчивается на _HEAD. Они всегда должны быть прописаны в верхнем регистре, как это.)

  • Ссылки делятся на пространства имен . Два, которые вы используете постоянно, это пространство имен branch , которое представляет собой каждый ref, орфография которого начинается с refs/heads/, и тег namespace, то есть каждый реф, чье имя начинается с refs/tags/. Есть и третий, который вы также используете e все время: имена для удаленного отслеживания - это ссылки, чье имя начинается с refs/remotes/. После слова remotes и его завершающего sla sh, Git добавляется имя рассматриваемого пульта, например origin, и другого завершающего sla sh.

Следовательно, ref - это просто общая форма любой ветви, тега, имени для удаленного отслеживания или любого другого имени в Git. Есть некоторые менее часто используемые и внутренние, такие как refs/stash для команды git stash, refs/bisect/ для git bisect и т. Д .; обычно вы их вообще не видите.

Вы видите имена веток, тегов и удаленного слежения, но Git обычно удаляет часть "пространства имен" имени :

  • master на самом деле refs/heads/master, но Git лишено части refs/heads/.
  • v1.2 действительно refs/tags/v1.2, но Git Снятая часть refs/tags/.
  • origin/master действительно refs/remotes/origin/master, но Git Снятая часть refs/remotes/.

Иногда Git только полосы refs/ часть из имен удаленного слежения. Не совсем понятно почему, но git branch -a делает это. Вот почему вы видите remotes/origin/master здесь. Сравните с git branch -r, где вы видите только origin/master. В любом случае это действительный способ express каждого имени, потому что существует правило из шести шагов для разрешения любого имени, которое вы даете, как показано в документации gitrevisions , и три шага включают в себя попытки поставить refs/remotes или refs/heads или refs/tags перед любым именем, которое вы дадите. Мы вернемся к этому через мгновение.

Большинство рефери хранят ровно одну вещь: идентификатор ha sh. Для имен филиалов и имен удаленного отслеживания этот идентификатор ha sh должен быть идентификатором commit ha sh. Для тегов это обычно либо идентификатор ha sh коммитов, либо идентификатор ha sh идентификатора аннотированного объекта тега , который затем сохраняет идентификатор коммитов ha sh. Этот дополнительный шаг - прохождение через объект тега - позволяет вам написать аннотированный тег или тег с сообщением.

Но некоторые ссылки symboli c ссылки Это означает, что вместо того, чтобы хранить идентификатор ha sh, они хранят имя другого ref . Наиболее распространенный - на самом деле, единственный, на мой взгляд, полезный - это очень особенный HEAD ref. 1

HEAD, обычно содержащий название ветки. То есть, если вы посмотрите на фактический файл .git/HEAD, вы увидите, например:

$ cat .git/HEAD
ref: refs/heads/master

Другими словами, name HEAD просто содержит название филиала master. Это означает, что master является текущей ветвью. Вот как Git реализует прикрепленный заголовок. Следовательно, detached HEAD - это как раз тот случай, когда HEAD содержит идентификатор коммита ha sh вместо имени ветви. Это действительно все, что есть в прикрепленной или отделенной голове. Git просто спрашивает себя: Имеет ли HEAD имя ветви? Если это так, эта ветвь является текущей веткой , а идентификатор фиксации ha sh хранится в этом имени ветви текущий коммит . Если нет, HEAD содержит фиксацию ha sh ID, и этот ha sh ID является текущим фиксацией.


1 HEAD очень особенный, потому что среди прочего, если файл пропадет, Git перестанет верить, что хранилище является хранилищем! Никогда не удаляйте .git/HEAD. Если после компьютера cra sh вам необходимо восстановить хранилище, у которого пропал файл HEAD, вы можете попробовать создать хранилище, содержащее ref: ref/heads/master, и посмотреть, позволяет ли это вам продолжить. Это происходит на удивление часто после cra sh, потому что HEAD является таким относительно активным файлом, и один из методов, который используют компьютерные системы для восстановления после cra sh, просто удаляет любой поврежденный файл.


Что все это означает

Как правило, ref должен преобразовать в коммит или другой га sh ID, для некоторого действительного, существующего, внутреннего Git объект. 2 Например, имя ветви, например master, может существовать , только если оно содержит идентификатор ha sh некоторого существующего действующего коммита.

Если ссылка содержит имя какой-либо другой ссылки, эта другая ссылка должна существовать и указывать действительный идентификатор ha sh. 3 Если другая ссылка не имеет существует, однако, мы можем сказать, что символ c ref это висящий .

Вот что это значит:

warning: symbolic ref is dangling: refs/remotes/origin/HEAD

Ваш существующий refs/remotes/origin/HEAD является символом c ссылка - все дистанционное отслеживание <em>remote</em>/HEAD имена являются символами c ссылки в конце концов - но какое бы имя оно ни содержало ns, что имя не существует.

Примечание : есть ситуация, в которой ваше собственное HEAD является ссылкой с висящим символом c. Обычно это происходит в новом, абсолютно пустом хранилище. HEAD должен существовать, так оно и есть. Он должен содержать название ветви, поэтому он содержит ref: refs/heads/master. Это символ c ref, говорящий о том, что вы находитесь на ветке master. Но это новый, абсолютно пустой репозиторий. В нем нет действительных коммитов! имя ветки master не может существовать, потому что имя ветви должно содержать идентификатор ha sh действительного, существующего коммита, а его нет. Таким образом, master само название ветви просто не существует. Это делает HEAD висячим символом.

Создание первого коммита создает имя master, разрешая ситуацию. Так что все решается само по себе, и в этой ситуации нет ничего плохого. Следовательно, свисающие символы c ref не вредны. Это особенно верно для HEAD (где Git не будет жаловаться на свисающие символы c ref), но это верно и для refs/remotes/origin/HEAD: все они безвредны. В отличие от специального случая для HEAD, они не полезны .


2 Обычно это коммит, но теги могут указывать на любой из четырех типов внутренних объектов Git. Разумеется, они должны иметь возможность указывать на аннотированные теговые объекты, чтобы вы могли иметь аннотированные теги. Git просто снимает здесь все ограничения, что позволяет им также указывать на объекты дерева или блобов.

3 Обратите внимание, что введение ссылок на символы c, которые разрешаются во время поиска ссылок, также вводит возможность циклов. Имя A может относиться к имени B , имя B относится к C, а затем C может относиться к A . Как вы решите это?

Упражнение: как git разрешит это? Относительно легко идентифицировать себя * l oop: если имя tumbolia говорит мой ответ получен при поиске имени "tumbolia" , вы можете сразу увидеть, глядя на до "тамболии", что ты будешь oop или останешься навсегда, глядя на себя снова и снова. Но как насчет длинных цепочек имен?

Упражнение: Ваша операционная система может предоставлять символические c ссылки или символические ссылки , которые являются файлами, содержимое которых является другими файлами ' имена. Если да, то как ваша ОС предотвращает или обнаруживает символьные петли c? (Git используется для реализации символов c ссылок через символические ссылки. Это изменилось, когда Git добавлена ​​поддержка Windows, поскольку многие системы Windows не предлагают символические ссылки.)


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

Давайте go вернемся к шестиэтапному процессу, который Git использует для разрешения введенного вами имени. Например, предположим, что вы запустили:

git rev-parse master

Попробуйте это. Попробуйте запустить git rev-parse с различными именами, а также с диапазонами, такими как master..develop, и с именами с добавленными операторами, такими как master~2. Затем go посмотрите на документацию gitrevisions снова и найдите это:

  1. Если существует $GIT_DIR/<refname>, это то, что вы имеете в виду (это обычно полезно только для HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD и CHERRY_PICK_HEAD);
  2. в противном случае, refs/<refname>, если оно существует;
  3. в противном случае, refs/tags/<refname>, если он существует;
  4. в противном случае, refs/heads/<refname>, если он существует;
  5. в противном случае, refs/remotes/<refname>, если он существует;

Три из этих пяти правил позволяют просто написать master или v1.2 или origin/master. Правило № 5 заботится о origin/master: поскольку refs/heads/origin/master существует, если вы запускаете git rev-parse origin/master и правила с 1 по 4 не работают, правило 5 работает, и на этом git rev-parse останавливается с допустимым коммитом ha sh Я БЫ. Вот что печатает git rev-parse.

Правило # 4 обрабатывает имена ветвей. Правило № 3 обрабатывает имена тегов. Обратите внимание, что правило № 3 означает, что если вы создаете тег с именем master, тег переопределяет ответвление , в большинстве случаев. 4 Если вы находитесь в такой ситуации, вы можете использовать правило № 2, написав heads/master или tags/master.

Но это исключает одно последнее правило. Вот оно:

в противном случае, refs/remotes/<refname>/HEAD, если он существует.

Это конкретное правило означает, что вы можете запустить:

git rev-parse origin

Git попробует остальные пять шагов, все из которых потерпят неудачу, а затем попытается проанализировать origin, как если бы вы написали refs/remotes/origin/HEAD. Если это имя существует и может быть преобразовано в идентификатор ha sh, то вы получите идентификатор ha sh.

В итоге все сводится к тому, что Вы можете использовать имя remote в качестве сокращения для значения имени удаленного слежения, которое у моего Git есть в его символах c ref под HEAD этого пульта дистанционного управления. , То есть, если у вас есть пульты с именами r1, r2 и r3, вы можете использовать имя r2 вместо записи refs/remotes/r2/HEAD (который работает без необходимости шестиэтапного процесса) или r2/HEAD (который работает с помощью шага № 5).

Как часто вы или кто-либо другой, на самом деле, используете это? Вот как полезны эти символы c. Никто из тех, кого я знаю, никогда его не использует, поэтому, насколько я могу судить, это бесполезно.


4 Команды, которые принимают или сначала пытаются использовать имя как ответвление имя выберет значение ответвление . Например, git checkout master проверит ветку . Но git rev-parse master не принимает имя ветви, поэтому он анализирует тег , находит его на шаге 3 и никогда не переходит на шаг 4.

Поэтому неразумно использовать одно и то же имя в качестве как ветви, так и имени тега. Git имеет правила, которые будут выбирать одно или другое, но они могут не соответствовать вашим личным ожиданиям!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...