Исправить Git оторванной головой?

1455

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

svn up .

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

git checkout HEAD^ src/

( srcкаталог, содержащий удаленный файл).

Теперь я узнаю, что у меня оторванная голова. Я понятия не имею, что это такое. Как я могу отменить?

Даниил
источник
69
git checkout masterвернет вас на главную ветку. Если вы хотите стереть любые изменения рабочей копии, вы, вероятно, захотите это сделать git reset --hard.
Абе Воелкер,
если бы ты не совершил, ты мог бы сделатьgit checkout -- src/
thesummersign
Попробуйте это: ссылка . Корочеcreate temp branch - checkout temp branch - checkout master - delete temp branch
фидев
@AbeVoelker Что вы имели в виду в комментариях working copy changes? Вы имеете в виду изменения, которые вы внесли в файлы после проверки другого коммита (т. Е. Изменения, которые вы сделали, находясь в отключенном состоянии головы)?
Минь

Ответы:

2149

Отделенная голова означает, что вы больше не находитесь на ветке, вы отметили один коммит в истории (в данном случае это коммит, предшествующий HEAD, т.е. HEAD ^).

Если вы хотите удалить свои изменения, связанные с отделенным HEAD

Вам нужно только проверить филиал, в котором вы были, например,

git checkout master

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

git checkout -- path/to/foo

Это восстановит файл foo до состояния, в котором он находится в индексе.

Если вы хотите сохранить ваши изменения, связанные с отделенным HEAD

  1. Выполнить git branch tmp- это сохранит ваши изменения в новой ветке под названием tmp.
  2. Запустить git checkout master
  3. Если вы хотите включить изменения, которые вы сделали master, запустите git merge tmpиз masterветки. Вы должны быть на masterветке после запуска git checkout master.
ralphtheninja
источник
6
«Это восстановит файл foo до состояния, в котором он был до того, как вы в него внесли какие-либо изменения». -> он восстановит его до состояния, в котором он находится в индексе - пожалуйста, отредактируйте
Mr_and_Mrs_D
88
Почему эта ошибка возникает в первую очередь? Это одна из вещей, за которые я ненавижу мерзавца - иногда совершенно случайное поведение. Никогда не было таких проблем с Mercurial.
Фиолетовый Жираф
97
@VioletGiraffe Это не ошибка и не что-то случайное - это просто состояние, в которое попадает ваш репозиторий при извлечении предыдущего коммита. «Отдельная голова» служит предупреждением о том, что вы также можете захотеть создать или указать ветку, если вы намерены выполнить какую-либо работу с этой точки. Но если вы просто хотите просмотреть этот тег или коммит, то нет ничего плохого в том, чтобы находиться в отдельном состоянии головы.
Нил Нейман
22
Не делайте этого, если вы посвятили себя отстраненной голове, смотрите другие ответы. Если да, вы можете проверить предыдущие упоминания об этом в Previous HEAD position was 7426948...
GD
9
@VioletGiraffe: у вас есть ментальная модель того, что происходит на основе Mercurial, но вы используете Git. Если вы не желаете подстраивать свою ментальную модель под модель Гита, тогда все будет казаться случайным. Как будто вы гуляете по улице с надетыми виртуальными очками и думаете, что летите на самолете, но вы действительно пересекаете улицу. Тебя будут сбивать машины.
иконоборчество
477

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

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work

Извлеченный из:

Что делать с коммитом сделанным в отстраненной голове

Тони Гамез
источник
27
Я считаю, что это предпочтительное решение, особенно если вы хотите сохранить изменения, внесенные вами при проверке отдельной версии.
adswebwork
10
@adswebwork: я согласен. Все остальные ответы предполагают возврат к предыдущему состоянию и потерю изменений, внесенных локально в отключенном состоянии головы.
Sk8erPeter
6
почему нет git stash? Это первое, что приходит мне в голову. Создание новой ветки будет излишним.
thesummersign
2
Вы также можете git rebase my-temporary-workи затем удалить ветку, git branch -d my-temporary-workчтобы она выглядела так, как будто вы в первую очередь зафиксировали правильную ветку.
Золтан
@geekay git stashзвучит как идеальный инструмент для этого случая. Не могли бы вы написать ответ с предложенными шагами для достижения этой цели?
Золтан
157

Решение без создания временной ветки.

Как выйти («исправить») состояние отключенного HEAD, когда вы уже что-то изменили в этом режиме и, при желании, хотите сохранить свои изменения:

  1. Внесите изменения, которые вы хотите сохранить. Если вы хотите перенять какие-либо изменения, сделанные вами в отключенном состоянии HEAD, зафиксируйте их. Подобно:

    git commit -a -m "your commit message"
    
  2. Отменить изменения, которые вы не хотите сохранять. При аппаратном сбросе будут отменены все незафиксированные изменения, которые вы сделали в отключенном состоянии HEAD:

    git reset --hard
    

    (Без этого шаг 3 потерпел бы неудачу, жалуясь на измененные незафиксированные файлы в отдельном HEAD.)

  3. Проверьте свою ветку. Выйдите из отключенного состояния HEAD, проверив ветку, над которой вы работали ранее, например:

    git checkout master
    
  4. Возьмите на себя ваши коммиты. Теперь вы можете взять коммиты, которые вы сделали в отдельном состоянии HEAD, путем выбора вишни, как показано в моем ответе на другой вопрос .

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    
tanius
источник
Это git reset --hardбыло именно то, что мне было нужно, потому что я хочу, чтобы исходным кодом был источник, и локальные изменения должны быть удалены.
Маркус Зеллер
Отличный ответ, это сработало для меня
MGLondon
130

Отдельная голова означает:

  1. Вы больше не на ветке,
  2. Вы проверили один коммит в истории

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

  git checkout master

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

В случае отсоединенного HEAD коммиты работают как обычно, за исключением того, что ни одна из названных веток не обновляется. Чтобы обновить основную ветвь с вашими зафиксированными изменениями, создайте временную ветвь там, где вы находитесь (таким образом, временная ветвь будет иметь все зафиксированные изменения, сделанные вами в отсоединенном HEAD), затем переключитесь на основную ветвь и объедините временную ветвь с хозяин.

git branch  temp
git checkout master
git merge temp
Разан Пол
источник
2
отлично, потом после удаления ветки темп
Дави Менезес
64

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

Я совершил изменения.

$ git commit -m "..."
[detached HEAD 1fe56ad] ...

Я вспомнил хеш (1fe56ad) коммита. Тогда я проверил ветку, на которой я должен был быть.

$ git checkout master
Switched to branch 'master'

Наконец я применил изменения коммита к ветке.

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...

Я думаю, что это немного проще, чем создание временной ветки.

Филипп Гербер
источник
2
Это должно быть ответом. Он возвращает ваши обнаженные файлы.
Слепой Странник
2
Да, это действительно самое простое - достаточно просто запомнить, не ища в Интернете, когда это произойдет в следующий раз. Зафиксируйте, обратите внимание на хэш, вернитесь к ветке, которую вы хотели зафиксировать, и git cherry-pick <hash>.
Мейсон
Спасибо за решение. Это помогло. Могу ли я также добавить, что мне нужно было сделать «мастер-источник происхождения git push», чтобы мой мастер и источник / мастер указывали на один и тот же коммит.
turnip424
1
По сути, это ответ Танюса (опубликовано более года назад).
Питер Мортенсен
Спасибо этому радостному выбору отменить последние изменения головы отделения
Omega Cube
55

Если вы внесли некоторые изменения, а затем поняли, что находитесь на отсоединенной голове, для этого есть простое решение: stash -> checkout master -> stash pop:

git stash
git checkout master   # Fix the detached head state
git stash pop         # Or for extra safety use 'stash apply' then later 
                      #   after fixing everything do 'stash drop'

Вы будете иметь свои незафиксированные изменения и нормальную «прикрепленную» ГОЛОВКУ, как будто ничего не произошло.

mojuba
источник
2
Сделал закладку для этого плохого мальчика - спасает, делая временную ветвь. Работал лакомство
Тим Тайлер
1
Я часто оказываюсь в отсоединенном состоянии HEAD после проверки подмодуля git и внесения в него изменений. Я считаю, что это лучшее и простое решение для исправления ошибок, чтобы я мог сохранить свои изменения.
user5359531
1
Это не работает, если вы уже зафиксировали изменения в отключенном состоянии?
Даниэль
40

Когда вы извлекаете конкретный коммит git, вы попадаете в состояние отдельного заголовка ... то есть ваша рабочая копия больше не отражает состояние именованной ссылки (например, "master"). Это полезно для изучения прошлого состояния хранилища, но не того, что вы хотите, если вы действительно пытаетесь отменить изменения.

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

git checkout myfile

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

git reset --hard HEAD^

Тем не менее, если вы делитесь хранилищем с другими людьми, a git resetможет быть разрушительным (поскольку оно стирает часть истории хранилища). Если вы уже поделились изменениями с другими людьми, вы, как правило, хотите git revertвместо этого посмотреть , что генерирует «антикоммит», то есть создает новый коммит, который «отменяет» рассматриваемые изменения.

Книга Git имеет больше деталей.

larsks
источник
1
Как я уже сказал в ответе @ ralphtheninja, это git checkout path/to/fooможет привести к конфликту git checkout some-branch, поэтому было бы лучше использовать его, git checkout -- path/to/fooчтобы избежать этих конфликтов.
Диего Лаго
30

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

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

введите описание изображения здесь

Другими словами:

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

Чтобы лучше понять ситуации с прикрепленной / отсоединенной головкой, давайте покажем шаги, ведущие к четверке рисунков выше.

Мы начинаем с того же состояния хранилища (изображения во всех квадрантах одинаковы):

введите описание изображения здесь


Теперь мы хотим выполнить git checkout- с различными целями в отдельных изображениях (команды на них сверху серый цвет , чтобы подчеркнуть , что мы только собираемся применить эти команды):

введите описание изображения здесь


Это ситуация после выполнения этих команд:

введите описание изображения здесь

Как вы можете видеть, точки Отправляйтесь к цели по git checkoutкоманде - на ветку (первые 3 изображения квадруплета), или (непосредственно) до фиксации (последнее изображение четверки).

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


Итак, мы сейчас находимся в той же ситуации, что и в начале этого ответа:

введите описание изображения здесь

MarianD
источник
6
Не читал, но проголосовал за красивые фотографии, которые вы сделали;).
Карло Вуд
@ Карло, спасибо!
MarianD
22

Так как «состояние отдельного заголовка» приводит вас к временной ветке, просто используйте, git checkout -которая ставит вас на последнюю ветку, на которой вы были.

Майк
источник
1
будьте осторожны, вы потеряете все коммиты, сделанные вами, когда вы находились в состоянии отсоединения головы.
Ajak6
@ Ajak6 Ты не теряешь эти коммиты. Они по-прежнему доступны через git reflogи могут быть перенесены в новый филиал или через git cherry-pickсуществующий филиал. Смотрите этот вопрос .
Танус
7

Чтобы уточнить ответ @Philippe Gerber, вот он:

мерзавец

Прежде cherry-pick, git checkout masterв этом случае необходимо. Кроме того, она необходима только с commitин detached head.

Timo
источник
6

добавление

Если ветка, в которую вы хотите вернуться, была последней сделанной вами проверкой, вы можете просто использовать checkout @{-1}. Это вернет вас к предыдущей проверке.

Кроме того, вы можете использовать псевдоним этой команды, например, git global --config alias.prevтак что вам просто нужно набрать, git prevчтобы вернуться к предыдущей проверке.

Дэвид Брауэр
источник
4

Нахождение в «отделенной голове» означает, что HEAD ссылается на конкретную безымянную фиксацию (как противоположность именованной ветви) (см. Раздел https://git-scm.com/docs/git-checkout Detached head )

Чтобы решить проблему, вам нужно только выбрать ветку, которая была выбрана ранее

git checkout @{-1}

Патент ANDRIA
источник
2

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

git add .

Но если вы только изменили или удалили существующие файлы, вы можете добавить (-a) и зафиксировать сообщение (-m) одновременно с помощью:

git commit -a -m "my adjustment message"

Затем вы можете просто создать новую ветку с вашим текущим состоянием с помощью:

git checkout -b new_branch_name

У вас будет новая ветка, и все ваши настройки будут в этой новой ветке. Затем вы можете продолжить нажимать на пульт и / или оформить заказ / вытащить / объединить, как вам угодно.

DZet
источник
2

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

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

После этого ... оформить нужную ветку с помощью команды:

Допустим, вы хотите ветку MyOriginalBranch:

git checkout -b someName origin / MyOriginalBranch

Дирендра Гаутам
источник
1

Гит сказал мне, как это сделать.

если вы набрали:

git checkout <some-commit_number>

Сохранить статус

git add .
git commit -m "some message"

Затем:

 git push origin HEAD:<name-of-remote-branch>
Стерлинг Диаз
источник
1

Я хотел сохранить свои изменения так, я просто исправляю это, делая ...

git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH

это работа для меня

CRLZXO
источник
1

Обычно HEADуказывает на ветку. Когда он не указывает на ветку, а когда он указывает на хеш коммита, 69e51это означает, что у вас есть отсоединенный HEAD. Вам нужно указать две ветки, чтобы решить проблему. Вы можете сделать две вещи, чтобы исправить это.

  1. git checkout other_branch // Невозможно, когда вам нужен код в этом коммите hash
  2. создайте новую ветку и укажите хеш коммита на только что созданную ветку.

HEAD должен указывать на ветвь, а не хеш коммита - золотое правило.

Кришнадас ПК
источник
Вот почему у меня была эта самая ошибка. Я вернулась к ревизии, а затем снова вернулась к текущей / последней ревизии, вместо того, чтобы проверить ветку, которая бы правильно прикрепила головку. Спасибо за помощь.
Рахул Тхакур
1

Вы, вероятно, сделали git reset --hard origin/your-branch.

Попробуй просто git checkout your-branch

Джонни Кейдж
источник
0
git pull origin master

работал на меня. Речь шла просто о явном указании удаленного имени и имени филиала.

Amjedonline
источник
0

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

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

falsarella
источник
0

Это работает для меня, он назначит новую ветку для отдельного руководителя:

git checkout new_branch_name detached_head_garbage_name

Алок Гупта
источник
0

Отделенная ГОЛОВА означает, что вы в настоящее время не находитесь ни в одной ветви. Если вы хотите сохранить текущие изменения и просто создать новую ветку, то вы делаете это:

git commit -m "your commit message"
git checkout -b new_branch

После этого вы, возможно, захотите объединить эту новую ветку с другими ветками. Всегда полезна команда git "собака" :

git log --all --decorate --oneline --graph
gebbissimo
источник