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

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

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

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

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

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

24 ответов


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

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

  • git symbolic-ref HEAD доходность refs/heads/master
    Ветка с именем "master"проверяется.
  • git rev-parse refs/heads/master доходность 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
    Поскольку это не символический ref, он должен указывать непосредственно на само обязательство.

у нас есть HEAD17a02998078923f2d62811326d130de991d1a95a

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

1 Это прекрасно, чтобы сделать "нормальную" работу с отдельной главой, вы просто должны отслеживать, что вы делаете, чтобы избежать рыбы за истории из reflog.


промежуточные шаги взаимодействующего ребасе сделаны с отделенной головой (частично для избежания загрязнять активную ветвь reflog). Если вы завершите полную операцию rebase, она обновит исходную ветвь с кумулятивным результатом операции 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 branch -d temp

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

git push origin master

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

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


просто сделать это:

git checkout master

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

git checkout -b temp
git checkout -B master temp

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

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

я подумал: Ага! Если HEAD является символическим именем для фиксации проверки currenty, я могу согласовать его с master путем rebasing оно против master:

git rebase HEAD master

этого команды:

  1. проверил master
  2. определяет родительские коммиты HEAD до точки HEAD отошли от master
  3. воспроизводит эти коммиты поверх 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

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

вы могли бы прийти в это состояние делает git checkout somecommit etc. и он предупредил бы вас следующим:--13-->

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

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

git checkout-b new_branch_name

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

сделать git reflog или даже просто git log и примечание патчи. Теперь git checkout master и git merge коммиты.

git merge HEAD@{1}

Edit:

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


получить ваш отдельный совершить на свою собственную ветку

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

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


Если у вас есть только master branch и вы хотите вернуться к "разработке" или функции, просто сделайте это :

git checkout origin/develop

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

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

затем

git checkout -b develop

это работает :)


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

git push origin HEAD:master

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


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

git rebase HEAD master
git checkout master

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


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

git push origin HEAD:master
git checkout master        
git pull

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

второй переходит к мастеру ветвей.

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

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


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

git branch -f master HEAD
git checkout master

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

git push -f

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


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

так, например, в ветке " dev " вы проверяете фиксацию asdfasd14314 ->

'git checkout asdfasd14314'

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

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

* (detached from asdfasdf)
  dev
  prod
  stage

но выйти из отстраненного главы государства и обратно за Дэва ->

'git checkout dev'

и тогда "git branch" будет список ->

* dev
  prod
  stage

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


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

git symbolic-ref HEAD выдает fatal: ref HEAD is not a symbolic ref

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

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

git symbolic-ref HEAD refs/heads/master

и голова re прилагается!


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

git branch temp
git checkout master
git merge temp

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


у меня была такая же проблема и я решил ее следующим образом.

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

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

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

  1. удаляет все неотслеживаемые файлы от вашего филиала бегите git clean -df.

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

  3. наконец, вы должны вернуть свою ветвь в главную ветвь с помощью .


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

git checkout master
git cherry-pick 99fe23ab

вместо git checkout origin/master

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

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


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

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

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


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

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

git branch -d branchname

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

git checkout branchname

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

понять на примере

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

совершить 1: master-->branch_HEAD (123be6a76168aca712aea16076e971c23835f8ca)

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

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

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

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


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

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

который я в конечном итоге исправил с

git push origin :HEAD

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

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'.

когда я лично оказываюсь в ситуации, когда оказывается, что я внес некоторые изменения, пока меня нет master (т. е. HEAD отсоединяется прямо над master и между ними нет коммитов) stashing может помочь:

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

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

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


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

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

после этого вы должны быть в состоянии подключиться к origin-master.


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