Git- Resolve Detached HEAD на сервере
Я довольно новичок в Git- я использую его только с тех пор, как начал работать на своего нынешнего работодателя.
Недавно я внес некоторые изменения на сервер, объединив исправление ошибки, выполненное коллегой на моей локальной машине разработки. Я сделал это, потянув их branch
на котором они реализовали исправление ошибки с сервера и слили его с моим локальным master
ветвь, которая была актуальной с живой версией кода. Я проверил это на своей локальной машине разработки, и все это, казалось, работало правильно, поэтому я отправил его на сервер.
Однако внесенные мною изменения, по-видимому, привели к появлению еще одной ошибки в живой версии (ошибка, которую она внесла, не была очевидна при локальном тестировании исправления и появилась только после того, как код был запущен).
Эта ошибка, которую я привел, фактически привела к недоступности интенсивно используемой части внутреннего веб-сайта компании, поэтому я сразу же проверил последние рабочие commit
& перезапустил сервер, чтобы сайт снова был доступен.
Сейчас я работаю над устранением проблем, которые вызвало исправление на моей локальной машине для разработки, перед тем, как снова отправить исправление на сервер, но после проверки старого commit
на сервере вышла живая версия проекта в виде detached HEAD
государство. detached HEAD
Укажите, что он в данный момент в основном функционален (то есть работает так же, как и до того, как мой коллега начал работать над исправлением этой ошибки, поэтому ошибка все еще присутствует).
Теперь я хочу разрешить detached HEAD
на сервере, чтобы я мог снова извлечь рабочий код с сервера, чтобы начать заново с этого момента, но я не уверен, как "сопоставить" остальную часть кода с detached HEAD
с которой я сейчас работаю.
Если я бегу git branch
на сервере вывод показывает, что у меня есть только master
ветвь (которая не работает - так как в ней есть ошибка, которую я ввел при нажатии на исходное исправление ошибки), и (detached from 0e57d3d)
, какой HEAD
на что сейчас указывают.
Другие сообщения, на которые я смотрел, указывают на то, что я должен оформить заказ master
для того, чтобы решить detached HEAD
, но я не могу этого сделать, так как знаю, что master
в настоящее время сломан.
Итак, как я могу прикрепить HEAD
опять же, чтобы код работал так же, как и в том состоянии, в котором он находился во время commit
что HEAD
указывает на? Буду ли я просто запустить git branch
оттуда, затем проверить, что branch
и сделать это master
? Или есть какой-то другой способ сделать это?
1 ответ
На первый взгляд, это выглядит как копия отсоединенной головы Fix a Git? Это в некоторых отношениях, а не в других. Кроме того, как сказал Торбьерн Равн Андерсен в различных комментариях, вы, вероятно, также захотите координировать свои действия с другими коллегами. Тем не менее, давайте сделаем несколько замечаний, которые не включены (и не соответствуют) другому вопросу.
Отдельная ГОЛОВА ничего не меняет - во всяком случае, пока
Во-первых, "отсоединенный HEAD" просто означает, что вы извлекли один конкретный коммит, часто по его хеш-идентификатору. Существует только одно функциональное различие между этим и git checkout branch-name
поскольку это также проверяет один конкретный коммит, и это звучит как круговое определение, потому что оно таково: разница в том, что когда вы делаете это, вы находитесь на ветви, а когда вы делаете это, вы не находитесь на ветви, то есть, у вас есть отдельная ГОЛОВА.
Следовательно, все "отдельные головы" означает "не на ветке". То есть, если вы проверяете один конкретный коммит и попадаете на ветку, вы "на ветке", так как git status
скажет; но если вы проверяете тот же конкретный коммит и не входите в ветку, у вас есть "отсоединенная голова", как git status
скажет.
git checkout
как вы попадаете или выключаете ветку
Есть только одна ориентированная на пользователя команда Git, чтобы попасть в какую-то конкретную ветку или отсоединить вашу HEAD, чтобы выйти из ветки, и это git checkout
, если ты git checkout
имя ветки, оно проверяет этот коммит и помещает вас в ветку. если ты git checkout
что-нибудь еще - включая тег, или ветку удаленного отслеживания, или необработанный хэш-идентификатор - это дает вам отсоединенный заголовок. Следовательно, как в ответе на этот другой вопрос, если вы просто хотите вернуться на ветку master
, ты только git checkout master
,
Ты бежал git checkout 1234567
или аналогичный, чтобы проверить более старый коммит, и теперь у него есть "отдельная ГОЛОВА".
Но git checkout
также обновляет ваш индекс и / или рабочее дерево
(Очень короткое напоминание: рабочее дерево - это то, где Git пишет и читает обратно копии того, что вы в конечном итоге сохраняете навсегда как коммиты в хранилище. Это в форме, понятной для остальных систем компьютера, вместо Git-файла. специфическая форма. Индекс - это место, где вы и Git создаете следующий коммит, который вы сделаете, он имеет форму, очень специфичную для Git, и имеет дополнительный цикл для координации между внутренней формой, специфичной для Git, и формой "обычного использования компьютера". коммиты - это, по сути, сохраненные индексы, минус лишний цикл.)
Ваш сервер, очевидно, работает за пределами рабочего дерева - и причина, по которой вы запустили git checkout 1234567
во-первых, потому что коммит это верхушка ветви master
, который является некоторым коммитом, отличным от 1234567, не работает. если ты git checkout master
Вы снова сломаете сервер, восстановив коммит.
Здесь вам нужно координировать действия с другими, потому что для повторного присоединения вашей ГОЛОВКИ вы должны сделать по крайней мере одно из двух:
- создать новую ветку, или
- перезапустите сервер, хотя бы временно.
Чтобы создать новую ветку, используйте git checkout -b newbranch
Если вы хотите и можете, чтобы сервер находился "на ветке" без изменения коммитов, просто создайте новую ветку, подсказкой которой является текущий коммит. Для этого используйте git checkout -b
:
git checkout -b mostly-working
Теперь ваша ГОЛОВА прикреплена как вы на ветке mostly-working
, который вы только что создали. С индексом и рабочим деревом ничего не происходит, потому что имя новой ветви mostly-working
имена совершают 1234567 (или что-то еще, что вы извлекли ранее).
Этот коммит, вероятно, где-то позади master
, То есть, если бы мы рисовали часть графа коммитов, он бы выглядел так, прежде чем мы сделаем это git checkout -b
вещь:
...--o--o--*--o--o <-- master
^
commit 1234567
HEAD
Все это git checkout -b
действительно, добавляет новое имя, указывающее на этот же коммит. Чтобы нарисовать его в виде обычного текста, нам нужно сдвинуть несколько коммитов вверх или вниз (я пойду вверх):
o--o <-- master
/
...--o--o--* <-- mostly-working (HEAD)
^
still commit 1234567
Поскольку мы не переместили коммиты, индекс и рабочее дерево остаются без изменений.
Если вы делаете новые коммиты сейчас, они продвигают ветку
Просто для завершения вышесказанного, давайте посмотрим, что произойдет, если вы измените что-то в рабочем дереве, git add
, а также git commit
, Git сделает новый коммит в новой ветке mostly-working
:
o--o <-- master
/
...--o--o--o--* <-- mostly-working (HEAD)
(кстати, я пользуюсь *
здесь, чтобы отметить текущий коммит, а-ля git branch
маркировка текущей ветки).
То же самое происходит с отдельной головой
Допустим, вы не сделали git checkout -b
, но изменил файл и зафиксировал. Это сделало бы новый коммит как обычно, но вместо того, чтобы находиться в ветке, новый коммит был бы новым отдельным HEAD. То есть мы бы нарисовали новый коммит так:
o--o <-- master
/
...--o--o--o--* <-- HEAD
В этом и заключается разница между "на ветке" и "отделенной головой". Нет ничего особенного в том, чтобы быть "на ветке", кроме того, что новые коммиты, когда сделаны, продвигают эту ветку. Название ветви указывает на верхушку ветви. Когда ты git checkout
ветвь, вы проверяете самый верхний коммит этой ветки. Когда вы делаете новые коммиты, вы добавляете их в ветку, заставляя имя указывать на новый коммит. (Новый коммит сам по себе указывает на предыдущий HEAD
совершать.) С HEAD
просто говорит, какая ветка является текущей, обновляя имя ветви, чтобы указать на новую фиксацию, также обновляет HEAD
указать на новый коммит.
Когда у вас отсоединен HEAD, процесс точно такой же: новый коммит указывает на предыдущий коммит, а новый коммит становится новым HEAD
совершить. Там просто нет названия для этого коммита (ну, кроме HEAD
конечно, но HEAD
меняется, когда ты git checkout
!).