Как я могу согласовать отделенную головку с мастером / источником?

1345

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

Где-то недавно я сделал reset некоторых файлов, чтобы вытащить их из стадии фиксации, а затем сделал rebase -i, чтобы избавиться от пары недавних локальных коммитов. Теперь я в состоянии, которое я не совсем понимаю.

В моей рабочей области git log показывает точно, что я ожидаю - я нахожусь на правильном поезде с коммитами, которые мне не нужны, а новые там и т.д.

Но я просто нажал на удаленный репозиторий, и что там по-другому: пара коммитов, которые я убил в rebase, была нажата, а новые, которые были зафиксированы локально, там не были.

Я думаю, что "master/origin" отделяется от HEAD, но я не на 100% не понимаю, что это значит, как визуализировать его с помощью инструментов командной строки и как его исправить.

  • 0
    Вы выдвинули коммиты перед ребазингом?
  • 0
    @manojlds: Не уверен, что вы имеете в виду. Я оттолкнул некоторое время перед ребазом, но не сразу.
Показать ещё 4 комментария
Теги:

26 ответов

2149
Лучший ответ

Во-первых, давайте выясним, что такое HEAD и что он означает, когда он отсоединен.

HEAD - это символическое имя для текущего извлеченного коммита. Когда HEAD не отсоединен ("нормальная" 1 ситуация: у вас есть разветвленная ветвь), HEAD фактически указывает на ветку "ref", а ветвь указывает на коммит. Таким образом, HEAD "привязан" к ветке. Когда вы делаете новый коммит, ветка, на которую указывает HEAD, обновляется, чтобы указывать на новый коммит. HEAD следует автоматически, так как он просто указывает на ветку.

  • git symbolic-ref HEAD возвращает refs/heads/master
    Ветка с именем "мастер" извлечена.
  • git rev-parse refs/heads/master yield 17a02998078923f2d62811326d130de991d1a95a
    Этот коммит является текущим наконечником или "головой" главной ветки.
  • git rev-parse HEAD также дает 17a02998078923f2d62811326d130de991d1a95a
    Это то, что значит быть "символическим реф". Он указывает на объект через какую-то другую ссылку.
    (Символические ссылки изначально были реализованы как символические ссылки, но позже были заменены простыми файлами с дополнительной интерпретацией, чтобы их можно было использовать на платформах, которые не имеют символических ссылок.)

У нас есть HEADrefs/heads/master17a02998078923f2d62811326d130de991d1a95a

Когда HEAD отсоединен, он указывает непосредственно на коммит, а не косвенно указывает на один через ветвь. Вы можете думать об отделенной ГОЛОВЕ как о неназванной ветки.

  • git symbolic-ref HEAD завершается неудачно со fatal: ref HEAD is not a symbolic ref
  • git rev-parse HEAD дает 17a02998078923f2d62811326d130de991d1a95a
    Поскольку это не символьная ссылка, он должен указывать непосредственно на коммит.

У нас есть HEAD17a02998078923f2d62811326d130de991d1a95a

Важная вещь, которую следует помнить с отсоединенным HEAD, заключается в том, что если на коммит, на который он указывает, в противном случае нет ссылки (ни один другой реф не может его достичь), то он станет "висящим", когда вы извлекаете какой-то другой коммит. В конечном итоге такие оборванные коммиты будут удалены в процессе сборки мусора (по умолчанию они хранятся не менее 2 недель и могут храниться дольше, если на них ссылается reflog HEAD).

1 Совершенно нормально выполнять "обычную" работу с отдельным HEAD, вам просто нужно следить за тем, что вы делаете, чтобы не выискивать выпавшую историю из reflog.


Промежуточные шаги интерактивной перебазировки выполняются с помощью отдельного HEAD (частично во избежание загрязнения журнала активных веток). Если вы завершите полную операцию перебазирования, она обновит вашу исходную ветвь с совокупным результатом операции перебазирования и снова присоединит HEAD к исходной ветке. Я предполагаю, что вы никогда полностью не завершили процесс ребазирования; это оставит вас с отключенным HEAD, указывающим на коммит, который был недавно обработан операцией rebase.

Чтобы выйти из вашей ситуации, вы должны создать ветку, которая указывает на коммит, на который в данный момент указывает ваша отдельная голова:

git branch temp
git checkout temp

(эти две команды могут быть сокращены как git checkout -b temp)

Это присоединит вашу ГОЛОВУ к новой 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 чтобы указать на него:

git branch -f master temp
git checkout master

(эти две команды могут быть сокращенно git checkout -b master temp как git checkout -b master temp)

Затем вы можете удалить временную ветку:

git branch -d temp

Наконец, вы, вероятно, захотите нажать на восстановленную историю:

git push origin master

Возможно, вам придется добавить --force в конец этой команды, чтобы нажать, если удаленная ветвь не может быть "быстро перенаправлена" к новому коммиту (т. --force или переписали какой-то существующий коммит, или иным образом переписали некоторый фрагмент истории).).

Если вы выполняли операцию перебазирования, вам, вероятно, следует ее очистить. Вы можете проверить, выполнялся ли ребазинг, .git/rebase-merge/ каталог .git/rebase-merge/. Вы можете вручную очистить в -p rogress rebase, просто удалив этот каталог (например, если вы больше не помните цель и контекст активной операции rebase). Обычно вы использовали бы git rebase --abort, но это делает некоторую дополнительную перезагрузку, которую вы, вероятно, хотите избежать (она перемещает HEAD обратно в исходную ветвь и сбрасывает ее обратно в исходную фиксацию, что отменит часть работы, которую мы делали выше).

  • 0
    Это также может помочь некоторым: sitaramc.github.com/concepts/detached-head.html
  • 5
    Интересно от man git-symbolic-ref : "В прошлом .git/HEAD была символической ссылкой, указывающей на refs/heads/master . Когда мы хотели переключиться на другую ветку, мы делали ln -sf refs/heads/newbranch .git/HEAD , и когда мы захотели выяснить, в какой ветке мы находимся, мы сделали readlink .git/HEAD . Но символические ссылки не являются полностью переносимыми, поэтому теперь они устарели, и символические ссылки (как описано выше) используются по умолчанию. «.
Показать ещё 17 комментариев
576

Просто сделайте следующее:

git checkout master

Или, если у вас есть изменения, которые вы хотите сохранить, сделайте следующее:

git checkout -b temp
git checkout -B master temp
  • 238
    Спасибо за краткость. Не у всех есть время для ответа «Во-первых, давайте уточним, что такое ГОЛОВА ...».
  • 49
    Это опасный ответ. Люди, приходящие к этому ответу, имеют разные состояния и ответы «просто сделай это, чтобы исправить это» не отвечают на вопросы. Этот может легко разрушить работу.
Показать ещё 8 комментариев
109

Я столкнулся с этой проблемой, и когда я прочитал в главном голосовавшем ответе:

HEAD - это символическое имя для текущего зафиксированного фиксации.

Я подумал: Ах-ха! Если HEAD - это символическое имя фиксации currenlty checkout, я могу согласовать его с master, переустановив его на master:

git rebase HEAD master

Эта команда:

  • проверяет master
  • идентифицирует родительские коммиты HEAD назад в точку HEAD, отклоненную от master
  • выполняет те коммиты поверх master

Конечным результатом является то, что все фиксации, которые были в HEAD, но не master, также находятся в master. master остается проверенным.


Относительно пульта дистанционного управления:

пара коммитов, которые я убил в rebase, была нажата, а новые, которые были зафиксированы локально, отсутствуют.

Удаленная история больше не может быть быстро переадресована с использованием локальной истории. Вам потребуется принудительно нажать (git push -f), чтобы перезаписать удаленную историю. Если у вас есть соавторы, обычно имеет смысл координировать это с ними, чтобы все были на одной странице.

После того, как вы нажмете master на удаленный origin, ваша ветвь удаленного отслеживания origin/master будет обновлена, чтобы указать на ту же фиксацию, что и master.

  • 3
    git: «Во-первых, перемотайте голову, чтобы воспроизвести вашу работу поверх нее ... Быстро продвинутый мастер в HEAD». я: "хорошо!"
  • 0
    Довольно круто!!!!
76

Посмотрите, пожалуйста, основное объяснение отсоединенной головы:

http://git-scm.com/docs/git-checkout

Командная строка для визуализации:

git branch

или

git branch -a

вы получите вывод, как показано ниже:

* (no branch)
master
branch1

* (no branch) показывает, что вы находитесь в отдельной голове.

Вы могли бы прийти к этому состоянию, выполнив git checkout somecommit и т.д., и он предупредил бы вас со следующим:

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

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

git checkout -b new_branch_name

Теперь, чтобы получить их на мастер:

Сделайте git reflog или даже просто git log и обратите внимание на свои фиксации. Теперь git checkout master и git merge совершает.

git merge HEAD@{1}

Edit:

Чтобы добавить, используйте git rebase -i не только для удаления/убийства, которые вам не нужны, но и для их редактирования. Просто укажите "изменить" в списке фиксации, и вы сможете внести поправки в фиксацию, а затем выпустить git rebase --continue, чтобы продолжить. Это обеспечило бы, чтобы вы никогда не приходили к отдельной голове.

  • 0
    Спасибо за детали и отличные информационные указатели здесь. Похоже, явного слияния не было необходимости, но это визуализировало некоторые концепции, к которым я вернусь. Благодарю.
  • 5
    Что делает "@ {1}"?
31

Получите отдельную фиксацию на свою ветку

Просто запустите git checkout -b mynewbranch.

Затем запустите git log, и вы увидите, что commit теперь HEAD в этой новой ветке.

  • 0
    Если я сделаю это, присоединяется ли mynewbranch к чему-либо?
  • 1
    Да, он прикрепляется к тому месту, где была бы прикреплена отсоединенная голова, и это именно то, что я хотел. Спасибо!
19

если у вас есть только мастер-ветвь и хотите вернуться к "разработке" или функция просто сделайте это:

git checkout origin/develop

Примечание: проверка источника/разработки.

Вы находитесь в состоянии отсоединенного HEAD. Вы можете осмотреться, сделать экспериментальную изменяет и фиксирует их, и вы можете отказаться от любых коммитов, которые вы совершаете в этом состояние, не влияя на какие-либо ветки, выполняя другую проверку...

затем

git checkout -b develop

Он работает:)

  • 7
    Для меня сработало не «git checkout origin / development», а «git checkout development». Использование «происхождение / развитие» всегда не приводило к изменениям, поэтому оставалось «HEAD отделено при происхождении / развитии». Пропуск части 'origin' исправил все.
16

Если вы хотите нажимать свою текущую головку (проверьте git log раньше), попробуйте:

git push origin HEAD:master

чтобы отправить отдельную HEAD в основную ветку в начале. Если ваше нажатие отклоняется, сначала попробуйте git pull origin master, чтобы получить изменения от источника. Если вы не заботитесь об изменениях, происходящих из источника, и отклонили его, потому что вы сделали преднамеренную перезагрузку, и вы хотите заменить источник/мастер своей текущей ветвью - тогда вы можете заставить ее (-f). Если вы потеряли некоторый доступ к предыдущим фиксациям, вы всегда можете запустить git reflog, чтобы просмотреть историю из всех ветвей.


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

git rebase HEAD master
git checkout master

Смотрите: Git: "В настоящее время нет ни одного ветки." Есть ли простой способ вернуться на ветку, сохраняя изменения?

  • 2
    Это действительно отправляет отделенные коммиты в origin / master. Чтобы прикрепить голову к локальной ветке, сделайте это: stackoverflow.com/a/17667057/776345
  • 0
    Когда я делаю это, я получаю, что этот репозиторий настроен для Git LFS, но «git-lfs» не был найден на вашем пути. Если вы больше не хотите использовать Git LFS, удалите этот хук, удалив .git / hooks / post-checkout.
9

Следующие работали для меня (используя только мастер ветвления):

git push origin HEAD:master
git checkout master        
git pull

Первый из них отодвигает отсоединенную головку к удаленному источнику.

Второе перемещается в мастер ветки.

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

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

  • 0
    не получилось, я получил: этот репозиторий настроен для Git LFS, но 'git-lfs' не найден на вашем пути. Если вы больше не хотите использовать Git LFS, удалите этот хук, удалив .git / hooks / pre-push. И вы в настоящее время не на ветке. Пожалуйста, укажите, с какой ветвью вы хотите объединиться.
7

Если вы полностью уверены, что HEAD - хорошее состояние:

git branch -f master HEAD
git checkout master

Вероятно, вы не можете нажать на начало координат, так как ваш мастер отклонился от источника. Если вы уверены, что никто другой не использует репо, вы можете принудительно нажать:

git push -f

Наиболее полезно, если вы находитесь в ветки функции, которую никто не использует.

  • 0
    правильный ответ прямо там
7

Сегодня я столкнулся с этим вопросом и довольно уверен, что решил это, выполнив следующие действия:

git branch temp
git checkout master
git merge temp

Я был на своем рабочем компьютере, когда я понял, как это сделать, и теперь я сталкиваюсь с той же проблемой на своем персональном компьютере. Поэтому придется подождать до понедельника, когда я вернусь на рабочий компьютер, чтобы увидеть, как я это сделал.

  • 1
    вторая команда git кажется неправильной ..
  • 0
    @StarShine Kenorb исправил это. Теперь он сохраняет ваши отдельные коммиты в новую ветку temp, переключается на master и сливает temp в master.
Показать ещё 1 комментарий
6

Как указал Крис, у меня была следующая ситуация.

git symbolic-ref HEAD не работает с fatal: ref HEAD is not a symbolic ref

Однако git rev-parse refs/heads/master указывал на хорошую фиксацию из того места, где я мог восстановить (в моем случае последний фиксатор, и вы можете видеть это commit с помощью git show [SHA]

После этого я сделал много грязных вещей, но то, что, похоже, было исправлено,

git symbolic-ref HEAD refs/heads/master

И голова прикреплена!

  • 1
    Спасибо! Моя голова оторвалась. Я мог догнать мастера, но они просто указывали на один и тот же коммит, а не на голову, указывающую на мастера, который указывал на коммит. Хороший совет = D
5

Все, что вам нужно сделать, это "git checkout [branch-name]", где [имя-ветки] - это имя исходной ветки, из которой вы попали в состояние отдельной головы. (Отсоединенный от asdfasdf) исчезнет.

Так, например, в ветке 'dev' вы проверяете фиксацию asdfasd14314 →

'git checkout asdfasd14314'

теперь вы находитесь в состоянии отдельной головы

'git branch' перечислит что-то вроде →

* (detached from asdfasdf)
  dev
  prod
  stage

но чтобы выйти из состояния отдельной головы и обратно в dev →

'git checkout dev'

а затем 'git branch' отобразит список →

* dev
  prod
  stage

но это, конечно, если вы не намерены сохранять какие-либо изменения в состоянии отдельной головы, но я нахожу, что делаю это много, не намереваясь внести какие-либо изменения, а просто посмотреть на предыдущую фиксацию

3

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

git checkout master
git cherry-pick 99fe23ab

Я подумал: я нахожусь на отдельной голове, но хочу быть на хозяине. Предполагая, что мое отдельное состояние не сильно отличается от мастера, если я могу применить свою фиксацию к мастеру, я бы установил. Это именно то, что делает вишня.

3

У меня была та же проблема, и я решил ее, выполнив следующие шаги.

Если вам нужно сохранить изменения

  • Сначала вам нужно запустить команду git checkout master, чтобы вернуть вас к мастеру филиал.
  • Если вам нужно сохранить изменения, запустите git checkout -b changes и git checkout -B master changes

Если вам не нужны ваши изменения

  • Чтобы удалить все неископанные файлы из вашей ветки git clean -df.

  • Затем вам нужно очистить все неустановленные изменения в вашем репозитории. Для этого вам нужно запустить git checkout --

  • Наконец, вы должны вернуть ветку в ведущую ветку с помощью команды git checkout master.

3

Вместо git checkout origin/master

просто сделай git checkout master

то git branch подтвердит вашу ветку.

3

Для меня это было так же легко, как удалить локальный филиал, так как у меня не было локальных коммитов, которые я хотел нажать:

Так я и сделал:

git branch -d branchname

И затем снова проверьте ветку:

git checkout branchname
2

Если вы сделали некоторые коммиты на вершине мастера и просто захотите "назад слить" master там (т.е. вы хотите, чтобы master указывал на HEAD), однострочный:

git checkout -B master HEAD
  • Это создает новую ветвь с именем master, даже если она уже существует (что похоже на перемещение master и то, что мы хотим).
  • Вновь созданная ветвь настроена на HEAD, где вы находитесь.
  • Новая ветка проверяется, поэтому вы находитесь на master после.

Я нашел это особенно полезным в случае субрепозиториев, которые также часто бывают в состоянии отсоединения.

1

Я нашел этот вопрос, когда вы ищете, что You are in 'detached HEAD' state.

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

Мой нормальный поток:

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
1

Когда я лично оказываюсь в ситуации, когда выясняется, что я внес некоторые изменения, пока я не в 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
1

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

Понять с примером

В большинстве случаев веткой является последовательность нескольких коммитов, таких как:

Зафиксировать 1: master--> branch_HEAD (123be6a76168aca712aea16076e971c23835f8ca)

Commit 2: master--> 123be6a76168aca712aea16076e971c23835f8ca → branch_HEAD (100644a76168aca712aea16076e971c23835f8ca)

Как вы можете видеть выше в случае последовательности коммитов, ваш филиал указывает на вашу последнюю фиксацию. Таким образом, в этом случае, если вы сделаете чек для совершения 123be6a76168aca712aea16076e971c23835f8ca, тогда вы будете находиться в состоянии отдельной головы, так как HEAD вашего ветки указывает на 100644a76168aca712aea16076e971c23835f8ca, и технически вы выгружаетесь в HEAD без ветки. Следовательно, вы находитесь в отдельном состоянии HEAD.

Теоретическое объяснение

В этом блоге четко указано, что репозиторий Git является древовидным коммитом, причем каждая фиксация, указывающая на своего предка с каждым указателем фиксации, обновляется, и эти указатели на каждую ветвь сохраняются в подкаталогах.git/refs. Теги хранятся в.git/refs/тегах и ветвях хранятся в.git/refs/heads. Если вы посмотрите на любой из файлов, вы обнаружите, что каждый тег соответствует одному файлу с хешем фиксации на 40 символов и, как объяснялось выше, @Chris Johnsen и @Ярослав Никитенко, вы можете проверить эти ссылки.

0

Это отлично сработало для меня:

1. git stash, чтобы сохранить ваши локальные изменения

Если вы хотите отменить изменения
git clean -df
git checkout -- .
git clean удаляет все необработанные файлы (предупреждение: в то время как оно не будет удалять игнорируемые файлы, упомянутые непосредственно в .gitignore, оно может удалять игнорируемые файлы, находящиеся в папках) и git checkout очищает все неустановленные изменения.

2. git checkout master, чтобы перейти к основной ветке (Предполагая, что вы хотите использовать мастер)
3. git pull, чтобы вытащить последнюю фиксацию из главной ветки
4. git status, чтобы проверить, что все выглядит великолепно.

On branch master
Your branch is up-to-date with 'origin/master'.
0

Если вы используете EGit в Eclipse: предположите, что ваш мастер является вашей основной ветвью развития

  • скопируйте изменения в ветку, как правило, новую
  • затем вытащите из пульта
  • затем щелкните правой кнопкой мыши узел проекта, выберите команду, затем выберите историю показа
  • затем щелкните правой кнопкой мастер, выберите
  • если Eclipse говорит вам, есть два мастера один локальный один удаленный, выберите удаленный

После этого вы сможете подключиться к исходному хозяину.

0

В моем случае я запустил git status, и я увидел, что в моем рабочем каталоге у меня есть несколько файлов без следа.

Чтобы сделать работу по перестановке, мне просто нужно было их очистить (так как они мне не нужны).

0

Я попал в действительно глупое состояние, я сомневаюсь, что кто-нибудь еще найдет это полезным... но на всякий случай

git ls-remote origin
0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b        HEAD
6f96ad0f97ee832ee16007d865aac9af847c1ef6        refs/heads/HEAD
0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b        refs/heads/master

который я окончательно установил с помощью

git push origin :HEAD
-1
git checkout checksum  # You could use this to peek previous checkpoints
git status # You will see HEAD detached at checksum
git checkout master # This moves HEAD to master branch
-2

У меня такая же проблема. Я спрятал свои изменения с помощью git stash и жестко перезапустил ветку в локальной до предыдущей фиксации (я думал, что это вызвало это), затем сделал git pull и теперь я не получаю эту голову. Не забывайте, что git stash apply чтобы снова внести изменения.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню