Почему мой репозиторий Git перешел в отключенное состояние HEAD?

Сегодня у меня была отстраненная голова, та же проблема, которая описана в: git push говорит, что все в курсе, хотя у меня есть локальные изменения

Насколько я знаю, я не делал ничего необычного, просто совершал и выталкивал из моего локального репо.

Так, как я закончил с detached HEAD?

15 ответов

Решение

Любая проверка коммита, который не является именем одной из ваших веток, даст вам отдельную ГОЛОВУ. SHA1, представляющий верхушку ветви, все равно дает отсоединенную головку. Только проверка названия локального филиала позволяет избежать этого режима.

Смотрите совершение с отстраненной головой

Когда HEAD отсоединен, коммиты работают как обычно, за исключением того, что ни одна из названных веток не обновляется. (Вы можете думать об этом как об анонимной ветке.)

альтернативный текст

Например, если вы извлекаете "удаленную ветвь", не отслеживая ее в первую очередь, вы можете получить отключенный HEAD.

Смотрите git: переключите ветку без отсоединения головы

Я воспроизвел это только сейчас случайно:

  1. списки удаленных веток

    git branch -r
          origin/Feature/f1234
          origin/master
    
  2. Я хочу оформить заказ на месте, поэтому я вырезал пасту:

    git checkout origin/Feature/f1234
    
  3. Presto! Отделенное состояние HEAD

    You are in 'detached HEAD' state. [...])
    

Решение № 1:

Не включать origin/ в начале моей спецификации ветки при проверке:

git checkout Feature/f1234

Решение № 2:

добавлять -b параметр, который создает локальную ветку с удаленного

git checkout -b origin/Feature/f1234 или же

git checkout -b Feature/f1234 он автоматически вернется к исходной точке

Detached HEAD означает, что то, что сейчас проверено, не является локальным филиалом.

Некоторые сценарии, которые приведут к Detached HEAD государство:

  • Если вы проверяете удаленную ветку, скажитеorigin/master. Это ветка только для чтения. Таким образом, при создании коммита изorigin/masterон будет свободно плавающим, т.е. не подключенным ни к какой ветви.

  • Если вы проверяете конкретный тег или коммит. При выполнении нового коммита отсюда он снова будет свободно перемещаться, то есть не связан ни с одной веткой. Обратите внимание, что когда ветка извлекается, новые коммиты всегда автоматически помещаются в конец.

    Если вы хотите вернуться и проверить конкретную фиксацию или тег, чтобы начать работу оттуда, вы можете создать новую ветвь, исходящую из этой фиксации, и переключиться на нее, git checkout -b new_branch_name. Это предотвратитDetached HEAD состояние, поскольку теперь у вас есть ветка, а не фиксация.

Пытаться

git reflog 

это дает вам историю того, как ваши заголовки и указатели веток перемещались в прошлом.

например:

88ea06b HEAD @ {0}: извлечение: переход от DEVELOPMENT к удаленным /origin/SomeNiceFeature e47bf80 HEAD@{1}: извлечение источника DEVELOPMENT: ускоренная перемотка вперед

верхняя часть этого списка - одна из причин, по которой можно столкнуться с состоянием DETACHED HEAD... проверить ветку удаленного отслеживания.

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

Пример: если "release/0.1" является именем тега, то

git checkout release/0.1

выдает отдельную ГОЛОВКУ при "выпуске / 0,1". Если вы ожидаете, что release / 0.1 будет именем ветви, то вы запутаетесь.

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

Вы можете посмотреть на вывод git log - вы можете вставить хвост журнала сюда с момента последнего успешного коммита, и мы все увидим, что вы сделали. Или вы можете вставить его и красиво спросить в #git на freenode IRC.

Если бы git переименовал detached HEADЯ бы назвал его HEAD, который не идентифицирован веткой и скоро будет забыт .

Мы, люди, легко запоминаем названия веток. Мы делаем git checkout new-button-feature / git checkout main. main и new-button-featureлегко запомнить. И мы можем просто сделать git branchи получите список всех веток. Но чтобы сделать то же самое с простыми коммитами, вам придется сделать git reflogчто очень утомительно. Потому что у вас тысячи коммитов, но очень мало веток.

Идентификатор отсоединенного коммита - это просто его SHA. Итак, предположим, вы проверили фиксацию (а не ветку), т.е. вы сделали git checkout d747dd10e450871928a56c9cb7c6577cf61fdf31 ты получишь:

Примечание: проверка 'd747dd10e450871928a56c9cb7c6577cf61fdf31'.

Вы находитесь в состоянии «отключенная ГОЛОВА».

...

Затем, если вы внесли какие-то изменения и сделали коммит, вы все еще НЕ в ветке.

Вы думаете, что запомните фиксацию SHA? Вы не будете!

git не хочет, чтобы это произошло. Следовательно, он сообщает, что ваш HEAD не связан с веткой, поэтому вы более склонны проверять новую ветку. В результате под этим сообщением также говорится:

Если вы хотите создать новую ветку для сохранения созданных вами коммитов, вы можете сделать это (сейчас или позже), снова используя -b с командой checkout. Пример:

git checkout -b


Если пойти немного глубже, ветка построена таким образом, чтобы она была умной. Он будет обновлять свой HEAD по мере того, как вы делаете коммиты. С другой стороны, теги не предназначены для этого. Если вы проверяете тег, то вы снова на отдельной ГОЛОВЕ. Основная причина заключается в том, что если вы делаете новую фиксацию из этого тега, а затем, учитывая, что на эту фиксацию не ссылается ничто (не какая-либо ветка или тег), она все равно считается отсоединенной HEAD.

Прикрепленные HEAD могут появиться только тогда, когда вы находитесь в ветке.

Подробнее см. Здесь

HEAD - это указатель, который прямо или косвенно указывает на конкретный коммит:

Прикрепленный HEAD означает, что он прикреплен к некоторой ветке (т.е. указывает на ветку).

Отсоединенный HEAD означает, что он не привязан к какой-либо ветке, то есть указывает непосредственно на какой-то коммит.

Если посмотреть под другим углом, если вы на ветке и получите:

      ref: refs/heads/Your-current-branch-name

Тогда, если вы это сделаете cat refs/heads/Your-current-branch-name тогда вы также увидите фиксацию, на которую указывает / ссылается ваша ветка.

Однако, если у вас была отделенная ГОЛОВА, вы и cat .git/HEAD вы просто получите SHA коммита и ничего больше:

      639ce5dd952a645b7c3fcbe89e88e3dd081a9912

Ни под чем более я подразумеваю, что голова не указывает ни на какую ветку. Он просто указывает на фиксацию.


В результате в любое время, когда вы проверяете фиксацию, даже если эта фиксация была последней фиксацией вашей основной ветки, вы все еще находитесь в отдельной HEAD, потому что ваша HEAD не указывает ни на какие ветки. Следовательно, даже проверка тега поместит вас в отдельную ГОЛОВУ.


Особая благодарность Джошу Касвеллу и Саагару Джа за то, что они помогли мне разобраться в этом.

Простой случайный способ сделать git checkout head как опечатка HEAD,

Попробуй это:

git init
touch Readme.md
git add Readme.md
git commit
git checkout head

который дает

Note: checking out 'head'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 9354043... Readme

Отдельная ГОЛОВА

является указателем на текущую извлеченную ветку или фиксацию, он отвечает на вопрос: где я сейчас в репозитории? может находиться в одном из двух состояний: прикрепленном (по умолчанию) или отсоединенном , в зависимости от того, проверили ли вы локальную ветку или нет.

ОП: Как у меня появился?

Операции, чем оставить HEAD в отдельном состоянии

В конце концов detached HEAD состояние может быть вызвано различными причинами, ниже приведены 5 распространенных случаев (возможно, вы выполняли одно из следующих действий):

  • Проверка конкретного коммита с помощью его хэша, т.е.
            $ git checkout 14ko3
    
  • Явная проверка удаленной ветки, т.е.
            $ git checkout origin/master
    
  • Переключение на ветку с использованием флага detached (Git 2.23), т.е.
            $ git switch master --detached
    
  • Проверка тега, т.е.
            $ git checkout v1.0.1
    
  • Выполнение интерактивной перебазировки (или регулярной перебазировки, содержащей конфликтующие изменения), т. Е.
            $ git rebase master feature-1 --interactive
    

В отключенном состоянии можно вносить экспериментальные изменения, не затрагивая существующие ветки. См. Инфографику ниже, иллюстрирующую разницу между committing в прикрепленном против отдельном состоянии.

Распространенное заблуждение состоит в том, что сообщение " Вы находитесь в состоянии" отключенная ГОЛОВА " имеет ошибочный тон, хотя на самом деле оно просто описывает, как HEAD ссылается на текущий снимок.

Переход из отключенного состояния в прикрепленное

Чтобы перейти из отсоединенного состояния в присоединенное, вы можете либо создать новую ветку с того места, где вы находитесь, либо вернуться к существующей ветке.

Примечание: любые коммиты, созданные в отсоединенном состоянии, в конечном итоге (после сборки мусора) будут отброшены, если вы переключитесь на другую существующую ветку без предварительного сохранения ваших изменений в новой ветке.

Источник: Выше взят отрывок из полной статьи по теме:Что такое HEAD в Git?

Другой способ войти в состояние git - это попытаться зафиксировать удаленную ветвь. Что-то вроде:

git fetch
git checkout origin/foo
vi bar
git commit -a -m 'changed bar'

Обратите внимание, что если вы сделаете это, любая дальнейшая попытка извлечения origin / foo вернет вас обратно в отдельное состояние!

Решение состоит в том, чтобы создать свою собственную локальную ветку foo, которая отслеживает origin / foo, а затем, по желанию, нажать.

Это, вероятно, не имеет ничего общего с вашей первоначальной проблемой, но эта страница высоко оценена Google по "git detached head", и этот сценарий недостаточно документирован.

Когда вы оформляете заказ на коммит git checkout <commit-hash> или к удаленной ветке ваш HEAD будет отключен и попытается создать на нем новый коммит.

Запреты, недоступные для какой-либо ветви или тега, будут собираться и удаляться из хранилища через 30 дней.

Другой способ решить эту проблему - создать новую ветку для вновь созданного коммита и оформить заказ. git checkout -b <branch-name> <commit-hash>

Эта статья иллюстрирует, как вы можете добраться до отдельного состояния HEAD.

Following VonC's comment, here is the short version of how I resolved this same 'detached HEAD' issue.

  1. Created a branch in my remote; origin/feature/dev
  2. In my local run git fetch, so now my local will be aware of this new remote branch
  3. Now run git switch feature/dev, and we are done!

Для других, которые могут искать способ получить имя ветки, но получаютHEADвместо этого вот что я придумал:

      const { execSync } = require('child_process');

const getBranchName = () => {
  let branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
  if (branch === 'HEAD') branch = execSync(`git branch -a --contains HEAD | sed -n 2p | awk '{ printf $1 }'`).toString().trim();
  return branch;
}

For my case it happens this way:

  • Create a new branch (feb_debugging).
  • Run git fetch
  • I see new branch (feb_debugging) pulled
  • Now, I use git checkout origin/feb_debugging

Here it gets me to HEAD is now at....

For fixing I just need another checkout

  • git checkout feb_debugging
  • Now git says that I am at feb_debugging branch.

Если нельзя использоватьgit switch, используйте «git checkout -b [ветка]» вместо «git checkout [ветка]»

Другие вопросы по тегам