Во-первых, давайте уточним что такое HEAD и что это означает, когда он отсоединен.
HEAD - символическое имя для текущего извлеченного коммита.Когда HEAD не отсоединен («нормальная» 1 ситуация: у вас есть ветвь извлечена), HEAD фактически указывает на «ref» ветки, а ветвь указывает на коммит.Таким образом, HEAD «привязан» к ветке.Когда вы делаете новый коммит, ветка, на которую указывает HEAD, обновляется, чтобы указывать на новый коммит.HEAD следует автоматически, так как он просто указывает на ветвь.
git symbolic-ref HEAD
урожайность refs/heads/master
Извлечена ветвь с именем «master». git rev-parse refs/heads/master
yield17a02998078923f2d62811326d130de991d1a95a
Этот коммит является текущим наконечником или «головой» главной ветви. git rev-parse HEAD
также дает 17a02998078923f2d62811326d130de991d1a95a
Это то, что значит быть «символическим реф»,Он указывает на объект через какую-то другую ссылку.
(Символические ссылки изначально были реализованы как символические ссылки, но позже были заменены простыми файлами с дополнительной интерпретацией, чтобы их можно было использовать на платформах, которые не имеют символических ссылок.)
У нас есть HEAD
→ refs/heads/master
→ 17a02998078923f2d62811326d130de991d1a95a
Когда HEAD отсоединен, он указывает непосредственно на коммит, а не косвенно указывает на него через ветвь.Вы можете думать об отделенной HEAD как о неназванной ветви.
git symbolic-ref HEAD
завершается с ошибкой fatal: ref HEAD is not a symbolic ref
git rev-parse HEAD
выход 17a02998078923f2d62811326d130de991d1a95a
Поскольку это не символьная ссылка, он должен указывать непосредственно на сам коммит.
У нас есть HEAD
→ 17a02998078923f2d62811326d130de991d1a95a
Важная вещь, которую следует помнить с отсоединенным HEAD, заключается в том, что если коммит, на который он указывает, не ссылается иначе (ни один другой реф не может достичьэто), тогда он станет «болтаться», когда вы проверяете какой-то другой коммит.В конечном итоге такие оборванные коммиты будут удалены в процессе сборки мусора (по умолчанию они хранятся не менее 2 недель и могут храниться дольше, если на них ссылается reflog HEAD).
1 Совершенно нормально выполнять «обычную» работу с отсоединенным HEAD, вам просто нужно следить за тем, что вы делаете, чтобы не выискивать выпавшую историю из рефлога.
Промежуточное звеношаги интерактивной перебазировки выполняются с помощью отдельного HEAD (частично, чтобы избежать загрязнения журнала активных веток).Если вы завершите полную операцию перебазировки, она обновит вашу исходную ветвь с совокупным результатом операции перебазирования и снова присоединит HEAD к исходной ветке.Я предполагаю, что вы никогда полностью не завершили процесс ребазирования;это оставит вас с отключенным HEAD, указывающим на коммит, который был последний раз обработан операцией rebase.
Чтобы восстановиться в вашей ситуации, вы должны создать ветку, которая указывает на коммит, на который в данный момент указывает ваш отсоединенныйHEAD:
git branch temp
git checkout temp
(эти две команды могут быть сокращены до git checkout -b temp
)
Это позволит снова присоединить HEAD к новой ветви 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
выглядит хорошо, вы можете обновить (например) master
, чтобы указать наit:
git branch -f master temp
git checkout master
(эти две команды могут быть сокращены до git checkout -B master temp
)
Затем можно удалить временную ветвь:
git branch -d temp
Наконец, вы, вероятно, захотите подтолкнуть reestablished history:
git push origin master
Возможно, вам понадобится добавить --force
в конец этой команды, чтобы нажать, если удаленная ветвь не может быть «быстро перенаправлена» к новому коммиту (т. е. вы отбросили илипереписал какой-то существующий коммит или иным образом переписал немного истории).
Если вы были в середине операции rebasen вы, вероятно, должны очистить его. Вы можете проверить, выполнялась ли перебазировка, найдя каталог .git/rebase-merge/
. Вы можете вручную очистить выполняющуюся перебазировку, просто удалив этот каталог (например, если вы больше не помните цель и контекст активной операции перебазировки). Обычно вы используете git rebase --abort
, но это делает некоторую дополнительную перезагрузку, которую вы, вероятно, хотите избежать (она перемещает HEAD обратно в исходную ветвь и сбрасывает ее обратно в исходную фиксацию, что отменит часть работы, которую мы делали выше).