Я новичок в разветвленных сложностях Git. Я всегда работаю в одной ветке и фиксирую изменения, а затем периодически перехожу к своему удаленному происхождению.
Где-то недавно я сделал сброс некоторых файлов, чтобы вывести их из постановки коммита, а затем сделал «ребазу -i», чтобы избавиться от пары недавних локальных коммитов. Сейчас я в состоянии, которое не совсем понимаю.
В моей рабочей области «git log» показывает именно то, чего я ожидал - я на правильном поезде с коммитами, которые я не хотел уходить, и новыми там и т. Д.
Но я просто подтолкнул к удаленному хранилищу, и что там отличается - пара коммитов, которые я убил в ребасе, была выдвинута, а новых, совершенных локально, там нет.
Я думаю, что «master / origin» отделен от HEAD, но я не совсем понимаю, что это значит, как визуализировать это с помощью инструментов командной строки и как это исправить.
Во-первых, давайте уточним , что такое HEAD и что это значит, когда он отсоединен.
HEAD - это символическое имя для текущего проверенного коммита. Когда HEAD не отсоединен («нормальный» 1 < / sup > ситуация: у вас есть ветка проверена), HEAD фактически указывает на «ref» ветки, а ветка указывает на коммит. ГОЛОВА, таким образом, «прикреплена» к ветке. Когда вы делаете новый коммит, ветка, на которую указывает HEAD, обновляется, чтобы указывать на новый коммит. ГОЛОВА следует автоматически, так как она просто указывает на ветку.
git canomic-ref HEAD
дает refs / heads / master
Филиал с именем «мастер» проверяется.git rev-parse refs / heads / master
17a02998078923f2d62811326d130de991d1a95a`
Этот коммит является текущим наконечником или «главой» основной ветви.git rev-parse HEAD
также дает 17a02998078923f2d62811326d130de991d1a95a
Вот что значит быть «символическим реф». Он указывает на объект через какую-то другую ссылку.
(Символические ссылки были первоначально реализованы как символические ссылки, но позже были изменены на простые файлы с дополнительной интерпретацией, чтобы их можно было использовать на платформах, которые не имеют символических ссылок.)У нас есть HEAD
→ refs / heads / master
→ 17a02998078923f2d62811326d130de991d1a95a
Когда HEAD отсоединяется, он указывает непосредственно на коммит, а не косвенно указывает на него через ветку. Вы можете думать о отдельно стоящей голове как о неназванной ветке.
git canomic-ref HEAD
не работает с fatal: ref HEAD не является символическим ref
git rev-parse HEAD
дает 17a02998078923f2d62811326d130de991d1a95a
Поскольку это не символический реф, он должен указывать непосредственно на сам коммит.У нас есть HEAD
→ 17a02998078923f2d62811326d130de991d1a95a
Важно помнить с отдельной HEAD, что если коммит, на который он указывает, не имеет ссылок (никакий другой реф не может достичь этого), то он станет «висящим», когда вы проверяете какой-либо другой коммит. В конце концов, такие свисающие коммиты будут обрезаны в процессе сбора мусора (по умолчанию они хранятся не менее 2 недель и могут храниться дольше, если на них ссылается журнал HEAD).
1 < / sup > Совершенно нормально выполнять «нормальную» работу с отдельным HEAD, вам просто нужно следить за тем, что вы делаете, чтобы не выловить историю из рефлога.
Промежуточные этапы интерактивного ребаза выполняются с помощью отсоединенной HEAD (частично, чтобы избежать загрязнения рефлекса активной ветви). Если вы закончите полную операцию ребазы, она обновит вашу исходную ветку с совокупным результатом операции ребазы и повторно прикрепит HEAD к исходной ветке. Я предполагаю, что вы никогда полностью не завершили процесс ребазы; это оставит вас с отстраненным HEAD, указывающим на коммит, который был недавно обработан операцией ребазы.
Чтобы оправиться от вашей ситуации, вы должны создать ветку, которая указывает на коммит, на который в данный момент указывает ваша отдельная HEAD:
git branch temp
git checkout temp
(эти две команды можно сократить как git checkout -b temp
) < / sub >
Это снова прикрепит вашу голову к новой ветке temp
.
Далее следует сравнить текущий коммит (и его историю) с обычной веткой, над которой вы ожидали работать:
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp
(Вы, вероятно, захотите поэкспериментировать с параметрами журнала: добавьте -p
, оставьте -- pretty = ...
, чтобы увидеть все сообщение журнала и т. Д.)
Если ваша новая ветка temp
выглядит хорошо, вы можете обновить ее (например,.) мастер
, чтобы указать на это:
git branch -f master temp
git checkout master
(эти две команды можно сократить как git checkout -B master temp
) < / sub >
Затем вы можете удалить временную ветку:
git branch -d temp
Наконец, вы, вероятно, захотите продвинуть восстановленную историю:
git push origin master
Возможно, вам придется добавить --force
в конец этой команды, чтобы нажать, если удаленная ветка не может быть «перенесена» в новый коммит (т.е. вы отказались или переписали какой-либо существующий коммит, или иным образом переписали часть истории).
Если вы были в середине операции ребаза, вам, вероятно, следует ее очистить. Вы можете проверить, находилась ли ребаза в процессе, ища каталог .git / rebase-merge /
. Вы можете вручную очистить незавершенную ребазу, просто удалив этот каталог (например,. если вы больше не помните цель и контекст операции активной ребазы). Обычно вы используете git rebase --abort
, но это делает некоторые дополнительные сбросы, которых вы, вероятно, хотите избежать (он перемещает HEAD обратно в исходную ветку и сбрасывает ее обратно в исходный коммит, что отменяет некоторые работы, которые мы сделал выше).
Просто сделай это:
git checkout master
Или, если у вас есть изменения, которые вы хотите сохранить, сделайте это:
git checkout -b temp
git checkout -B master temp
Я столкнулся с этой проблемой, и когда я прочитал в верхней части, проголосовал ответ:
HEAD - это символическое имя для текущего проверенного коммита.
Я подумал: а-ха! Если «HEAD» - это символическое имя для коммита проверки, я могу согласовать его с «master», изменив его на «master»:
git rebase HEAD master
Эта команда:
мастер
HEAD
обратно в точку HEAD
, отклоненную от master
master
Конечным результатом является то, что все коммиты, которые были в HEAD
, но не master
, также находятся в master
. master
остается проверенным.
Относительно пульта дистанционного управления:
пара коммитов, которые я убил в ребазе, была выдвинута, а новых, совершенных на месте, там нет.
Удаленная история больше не может быть перенесена с помощью вашей локальной истории. Вам нужно будет принудительно нажать (git push -f
), чтобы перезаписать удаленную историю. Если у вас есть сотрудники, обычно имеет смысл согласовать это с ними, чтобы все были на одной странице.
После того, как вы переместите master
в удаленный origin
, ваша ветка удаленного отслеживания origin / master
будет обновлена, чтобы указать на тот же коммит, что и master
.
Ищите здесь основное объяснение отстраненной головы:
http://git-scm.com/docs/git-checkout
Командная строка для визуализации:
git branch
или
git branch -a
Вы получите вывод, как ниже:
* (no branch)
master
branch1
* (без ветки)
показывает, что вы находитесь в отдельной голове.
Вы могли бы прийти в это состояние, выполнив «оформление заказа» и т. Д. и это предупредило бы вас следующим:
Вы находитесь в состоянии «отдельной головы». Вы можно осмотреться, сделать экспериментальным изменяет и фиксирует их, и вы можете отбросьте все коммиты, которые вы делаете в этом состояние без воздействия на какие-либо филиалы выполнив еще одну проверку.
Если вы хотите создать новую ветку Сохраните коммиты, которые вы создаете, вы можете сделать так (сейчас или позже) с помощью -b с Оформить заказ снова. Пример:
git checkout -b new_branch_name
Теперь, чтобы получить их на мастера:
Сделайте git reflog
или даже просто git log
и запишите свои коммиты. Теперь git checkout master
и git merge
коммиты.
git merge HEAD@{1}
Редактировать:
Чтобы добавить, используйте git rebase -i
не только для удаления / убийства коммитов, которые вам не нужны, но и для их редактирования. Просто укажите «править» в списке коммитов, и вы сможете изменить свой коммит, а затем выпустить «гит-ребазу - продолжайте», чтобы продолжить. Это гарантировало бы, что вы никогда не входили в отдельную голову .
Просто запустите git checkout -b mynewbranch
.
Затем запустите git log
, и вы увидите, что коммит теперь HEAD
в этой новой ветке.
если у вас есть только основная ветка и вы хотите вернуться к «разработке» или функции, просто сделайте это:
git checkout origin/develop
Примечание: проверка происхождения / разработки .
Вы находитесь в состоянии отдельно стоящей головы . Вы можете осмотреться, сделать экспериментальным изменяет и фиксирует их, и вы можете отказаться от любых коммитов, которые вы делаете в этом состояние без воздействия на какие-либо филиалы путем выполнения другого оформления заказа...
тогда
git checkout -b develop
Работает :)
Если вы хотите нажать свою текущую отдельную ГОЛОВУ (проверьте git log
раньше), попробуйте:
git push origin HEAD:master
отправить свою голову отдельно в основную ветку по происхождению. Если ваш толчок отклонен, сначала попробуйте git pull origin master
, чтобы получить изменения от происхождения. Если вас не волнуют изменения в происхождении, и они отклоняются, потому что вы сделали некоторую преднамеренную ребазу и хотите заменить origin / master своей текущей отдельно стоящей веткой - тогда вы можете заставить ее (-f
). Если вы потеряли доступ к предыдущим коммитам, вы всегда можете запустить git reflog
, чтобы увидеть историю из всех ветвей.
Чтобы вернуться к основной ветке, сохраняя изменения, попробуйте следующие команды:
git rebase HEAD master
git checkout master
Я только что столкнулся с этим вопросом сегодня и почти уверен, что решил его, сделав:
git branch temp
git checkout master
git merge temp
Я был на своем рабочем компьютере, когда понял, как это сделать, и теперь у меня возникла та же проблема на моем персональном компьютере. Поэтому придется подождать до понедельника, когда я вернусь за рабочим компьютером, чтобы точно узнать, как я это сделал.
Я нашел этот вопрос при поиске «Вы находитесь в состоянии« отдельно стоящей головы ».`
Проанализировав, что я сделал, чтобы попасть сюда, по сравнению с тем, что я делал в прошлом, я обнаружил, что допустил ошибку.
Мой нормальный поток:
git checkout master
git fetch
git checkout my-cool-branch
git pull
На этот раз я сделал:
git checkout master
git fetch
git checkout origin/my-cool-branch
# You are in 'detached HEAD' state.
Проблема в том, что я случайно сделал:
git checkout origin/my-cool-branch
Вместо того, чтобы:
git checkout my-cool-branch
Исправление (в моей ситуации) заключалось в том, чтобы просто запустить вышеупомянутую команду и затем продолжить поток:
git checkout my-cool-branch
git pull
Следующее работало для меня (используя только мастера филиала):
git push origin HEAD:master
git checkout master
git pull
Первый толкает отсоединенную ГОЛОВУ к удаленному происхождению.
Второй переходит к мастеру ветки.
Третий восстанавливает ГОЛОВУ, которая привязывается к мастеру ветки.
Проблемы могут возникнуть при первой команде, если толчок будет отклонен. Но это больше не будет проблемой отстраненной головы, а связано с тем, что отстраненная ГОЛОВА не знает о некоторых удаленных изменениях.
Если вы полностью уверены, что HEAD - это хорошее состояние:
git branch -f master HEAD
git checkout master
Вы, вероятно, не можете перейти к происхождению, так как ваш мастер отклонился от происхождения. Если вы уверены, что никто другой не использует репо, вы можете принудительно нажать:
git push -f
Наиболее полезно, если вы находитесь в ветке функций, которую никто не использует.
Как указал Крис, у меня была следующая ситуация
git icony-ref HEAD
не работает с fatal: ref HEAD не является символическим ref
Однако git rev-parse refs / heads / master
указывал на хороший коммит, с которого я мог восстановиться (в моем случае последний коммит, и вы можете увидеть этот коммит, используя git show [SHA]
После этого я сделал много грязных вещей, но то, что, кажется, исправило, справедливо
git canomic-ref HEAD refs / heads / master
И голова снова прикреплена!
Все, что вам нужно сделать, это «git checkout [branch-name]», где [branch-name] - это имя исходной ветви, из которой вы попали в состояние отсоединенной головки. (Отдельно от asdfasdf) исчезнет.
Так, например, в ветке 'dev' вы проверяете коммит asdfasd14314 - >
'git checkout asdfasd14314'
Вы сейчас в состоянии отстраненной головы
'git branch' будет перечислять что-то вроде - >
* (detached from asdfasdf)
dev
prod
stage
но выйти из состояния оторванной головы и вернуться к dev - >
'git checkout dev'
и тогда «фити-ветвь» будет перечислять - >
* dev
prod
stage
но это, конечно, если вы не намерены скрывать какие-либо изменения от состояния отстраненного головы, но я делаю это очень не собираюсь вносить какие-либо изменения, а просто смотрю на предыдущий коммит
У меня была эта проблема сегодня, когда я обновил подмодуль, но не был ни в одной ветке. Я уже совершил, поэтому тайка, касса, неукрытие не сработают. Я закончил тем, что выбрал коммит отстраненной головы. Поэтому сразу после того, как я совершил (когда толчок не удался), я сделал:
git checkout master
git cherry-pick 99fe23ab
Мое мышление пошло: я на обочине, но я хочу быть на хозяине. Предполагая, что мое отстраненное состояние не сильно отличается от мастера, если бы я мог применить свой коммит к мастеру, я был бы настроен. Это именно то, что делает вишня.
Если вы сделали несколько коммитов поверх мастера и просто хотите «слить назад» master
там (т.е. Вы хотите, чтобы master
указывал на HEAD
), однострочник был бы:
git checkout -B master HEAD
master
, даже если она уже существует (что похоже на перемещение master
и это то, что мы хотим).HEAD
, где вы находитесь.master
потом.Я нашел это особенно полезным в случае подрепозиторий, которые также довольно часто оказываются в отдельном состоянии.
Для меня это было так же просто, как снова удалить локальную ветку, так как у меня не было локальных коммитов, которые я хотел бы выдвинуть:
Так я и сделал
git branch -d branchname
А потом снова проверяю ветку:
git checkout branchname
У меня была та же проблема, и я решил ее, пройдя следующие шаги.
Если вам нужно сохранить свои изменения
git checkout master
, чтобы вернуть вас к мастеру
филиал.git checkout -b changes
и
git checkout -B master changes
Если вам не нужны ваши изменения
Чтобы удалить все неотслеживаемые файлы из вашей ветки, запустите git clean -df
.
Затем вам нужно очистить все неустановленные изменения в вашем хранилище. Для этого вам нужно запустить git checkout -
Наконец, вы должны вернуть свою ветку обратно в основную ветку с помощью команды git checkout master
.
Когда я лично оказываюсь в ситуации, когда оказывается, что я внес некоторые изменения, пока я не в «мастере» (т.е. HEAD
отсоединяется прямо над master
, и между ними нет коммитов), может помочь:
git stash # HEAD has same content as master, but we are still not in master
git checkout master # switch to master, okay because no changes and master
git stash apply # apply changes we had between HEAD and master in the first place
Проще говоря, отдельное состояние HEAD означает вы не проверяетесь на HEAD (или наконечник) какой-либо ветви .
Ветвь в большинстве случаев представляет собой последовательность нескольких коммитов, таких как:
Обязательство 1: master - > branch_HEAD (123be6a76168aca712aea16076e971c23835f8ca)
Обязательство 2: master - > 123be6a76168aca712aea16076e971c23835f8ca - > branch_HEAD (100644a76168aca712aea16076e971c23835f8ca)
Как вы можете видеть выше в случае последовательности коммитов, ваша ветка указывает на ваш последний коммит. Таким образом, в этом случае, если вы проверяете обязательство 123be6a76168aca712aea16076e971c23835f8ca , то вы будете в состоянии отсоединения, так как HEAD вашей ветви указывает на * 100644a76168aca712aea16076e971c2. Следовательно, вы находитесь в состоянии отстраненной головы.
В этом блоге это четко сказано Git-репозиторий - это дерево коммитов, причем каждый коммит указывает на своего предка, при этом каждый указатель коммита обновляется, и эти указатели на каждую ветку сохраняются в подкаталогах .git / refs. Теги хранятся в .git / refs / tags, а ветки хранятся в .git / refs / heads. Если вы посмотрите на любой из файлов, вы обнаружите, что каждый тег соответствует одному файлу с хешем-концептом из 40 символов, и, как объяснено выше @Chris Johnsen и @Yaroslav Nikitenko, вы можете проверить эти ссылки.