Исправить Git оторванной головой?
Я делал какую-то работу в своем хранилище и заметил, что файл имел локальные изменения. Я больше не хотел их, поэтому я удалил файл, думая, что я могу просто извлечь новую копию. Я хотел сделать Git эквивалент
svn up .
С помощью git pull
не похоже на работу. Случайный поиск привел меня на сайт, где кто-то рекомендовал делать
git checkout HEAD^ src/
(src
каталог, содержащий удаленный файл).
Теперь я узнаю, что у меня оторванная голова. Я понятия не имею, что это такое. Как я могу отменить?
33 ответа
Отдельная голова означает, что вы больше не находитесь на ветке, вы извлекли один коммит в истории (в данном случае это коммит, предшествующий HEAD, т.е. HEAD^).
Если вы хотите удалить свои изменения, связанные с отделенным HEAD
Вам нужно только проверить филиал, в котором вы были, например,
git checkout master
В следующий раз, когда вы изменили файл и хотите восстановить его до состояния, в котором он находится в индексе, сначала не удаляйте файл, просто сделайте
git checkout -- path/to/foo
Это восстановит файл foo до состояния, в котором он находится в индексе.
Если вы хотите сохранить ваши изменения, связанные с отделенным HEAD
- Бежать
git log -n 1
; это покажет самый последний коммит на отдельном заголовке. Скопируйте и вставьте хэш коммита. - Бежать
git checkout master
- Бежать
git branch tmp <commit-hash>
, Это сохранит ваши изменения в новой ветке под названиемtmp
, - Если вы хотите включить изменения, которые вы внесли в
master
, бежатьgit merge tmp
отmaster
ветка. Вы должны быть наmaster
ветвь после запускаgit checkout master
,
Если вы изменили файлы, которые не хотите потерять, вы можете нажать их. Я зафиксировал их в отдельном режиме, и после этого вы можете перейти во временную ветку для последующей интеграции в master.
git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work
Извлеченный из:
Решение без создания временной ветки.
Как выйти ("исправить") состояние отключенного HEAD, когда вы уже что-то изменили в этом режиме и, при желании, хотите сохранить свои изменения:
Внесите изменения, которые вы хотите сохранить. Если вы хотите перенять какие-либо изменения, сделанные вами в отключенном состоянии HEAD, зафиксируйте их. Подобно:
git commit -a -m "your commit message"
Отменить изменения, которые вы не хотите сохранять. При аппаратном сбросе будут отменены все незафиксированные изменения, которые вы сделали в отключенном состоянии HEAD:
git reset --hard
(Без этого шаг 3 потерпел бы неудачу, жалуясь на измененные незафиксированные файлы в отдельном HEAD.)
Проверьте свою ветку. Выйдите из отключенного состояния HEAD, проверив ветку, над которой вы работали ранее, например:
git checkout master
Возьмите на себя ваши коммиты. Теперь вы можете взять коммиты, которые вы сделали в отдельном состоянии HEAD, путем выбора вишни, как показано в моем ответе на другой вопрос.
git reflog git cherry-pick <hash1> <hash2> <hash3> …
HEAD - это указатель, который прямо или косвенно указывает на конкретный коммит:
Прикрепленный HEAD означает, что он прикреплен к некоторой ветке (т.е. указывает на ветку).
Отсоединенный HEAD означает, что он не привязан к какой-либо ветке, т.е. указывает непосредственно на какой-то коммит.
Другими словами:
- Если он указывает на фиксацию напрямую, HEAD отсоединяется.
- Если он косвенно указывает на фиксацию (т. Е. Указывает на ветку, которая, в свою очередь, указывает на фиксацию), HEAD прикрепляется.
Чтобы лучше понять ситуации с прикрепленной / отсоединенной HEAD, давайте покажем шаги, ведущие к четверке изображений выше.
Начнем с того же состояния репозитория (картинки во всех квадрантах одинаковые):
Теперь мы хотим выполнить git checkout
- с разными целями на отдельных изображениях (команды над ними затемнены, чтобы подчеркнуть, что мы будем применять только эти команды):
Вот такая ситуация после выполнения этих команд:
Как вы можете видеть, точки ГОЛОВЫ к цели изgit checkout
команда - на ветку (первые 3 изображения четверки) или (напрямую) на фиксацию (последнее изображение четверки).
Содержимое рабочего каталога также изменяется, чтобы соответствовать соответствующему фиксации (моментальному снимку), то есть фиксации, на которую указывает (прямо или косвенно) HEAD.
Итак, теперь мы находимся в той же ситуации, что и в начале этого ответа:
Отдельная голова означает:
- Вы больше не на ветке,
- Вы проверили один коммит в истории
Если у вас нет изменений: вы можете переключиться на мастер, применив следующую команду
git checkout master
Если у вас есть изменения, которые вы хотите сохранить:
В случае отсоединенного HEAD коммиты работают как обычно, за исключением того, что ни одна из названных веток не обновляется. Чтобы обновить основную ветвь с вашими зафиксированными изменениями, создайте временную ветвь там, где вы находитесь (таким образом, временная ветвь будет иметь все зафиксированные изменения, сделанные вами в отсоединенном HEAD), затем переключитесь на основную ветвь и объедините временную ветвь с хозяин.
git branch temp
git checkout master
git merge temp
Если вы внесли какие-то изменения, а затем поняли, что находитесь на отдельной голове, для этого есть простое решение: 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'
У вас будут ваши незафиксированные изменения и нормальная "прикрепленная" ГОЛОВА, как будто ничего не произошло.
Вот что я только что сделал, когда понял, что у меня отстраненная голова, и я уже внес некоторые изменения.
Я совершил изменения.
$ git commit -m "..."
[detached HEAD 1fe56ad] ...
Я вспомнил хеш (1fe56ad) коммита. Тогда я проверил ветку, на которой я должен был быть.
$ git checkout master
Switched to branch 'master'
Наконец я применил изменения коммита к ветке.
$ git cherry-pick 1fe56ad
[master 0b05f1e] ...
Я думаю, что это немного проще, чем создание временной ветки.
Когда вы проверяете конкретный коммит в git
вы попадаете в состояние отсоединенной головы... то есть ваша рабочая копия больше не отражает состояние именованной ссылки (например, "master"). Это полезно для изучения прошлого состояния хранилища, но не того, что вы хотите, если вы действительно пытаетесь отменить изменения.
Если вы внесли изменения в конкретный файл и просто хотите отменить их, вы можете использовать checkout
команда как это:
git checkout myfile
Это отменит любые незафиксированные изменения и вернет файл в любое состояние, в котором он находится в заголовке вашей текущей ветки. Если вы хотите отменить изменения, которые вы уже совершили, вы можете использовать reset
команда. Например, это вернет хранилище в состояние предыдущей фиксации, отбросив любые последующие изменения:
git reset --hard HEAD^
Однако, если вы делитесь хранилищем с другими людьми, git reset
может быть разрушительным (потому что это стирает часть истории хранилища). Если вы уже поделились изменениями с другими людьми, вы, как правило, хотите посмотреть на git revert
вместо этого, который генерирует "антикоммит", то есть создает новый коммит, который "отменяет" рассматриваемые изменения.
Книга Git имеет больше деталей.
Так как "отдельное состояние головы" приводит вас к временной ветке, просто используйте git checkout -
который помещает вас в последнюю ветку, на которой вы были.
Ты наверное сделал git reset --hard origin/your-branch
.
Попробуй просто git checkout your-branch
Нахождение в "отделенной голове" означает, что HEAD ссылается на конкретную безымянную фиксацию (как противоположность именованной ветви) (см. Раздел https://git-scm.com/docs/git-checkout Detached head)
Чтобы решить проблему, вам нужно только выбрать ветку, которая была выбрана ранее
git checkout @{-1}
Чтобы уточнить ответ @Philippe Gerber, вот он:
До cherry-pick
, git checkout master
необходимо в этом случае. Кроме того, это необходимо только с commit
в detached head
,
Чтобы добавить к ответу @ralphtheninja. Если вы получили это сообщение после использования
Пожалуйста, зафиксируйте свои изменения или спрячьте их, прежде чем переключать ветки. Прерывание
Затем вы можете просто принудительно оформить заказ, используя флаг -f следующим образом:
git checkout -f master
По-видимому, это приведет к потере всех изменений, сделанных в автономном режиме. Так что будьте осторожны при его использовании.
Отсоединенная голова означает, что вы не проверили свою ветку должным образом или только что проверили одну фиксацию.
Если вы столкнулись с такой проблемой, сначала сохраните локальные изменения, чтобы не потерять свои изменения.
После этого... проверьте нужную ветку с помощью команды:
Допустим, вам нужна ветка MyOriginalBranch:
git checkout -b someName origin / MyOriginalBranch
добавление
Если филиал, в который вы хотите вернуться, был последним оформленным заказом, вы можете просто использовать checkout @{-1}
, Это вернет вас к предыдущей проверке.
Кроме того, вы можете использовать псевдоним этой команды, например, git global --config alias.prev
так что вам просто нужно набрать git prev
чтобы вернуться к предыдущей проверке.
Я был в похожей ситуации.
По какой-то причине у меня была отделенная голова - я делал коммиты по тому же пути, что и ветка, в которой, как я думал, я находился - например, HEAD был дочерним элементом тега ветки, но по какой-то причине тег ветки остался на историческом совершить ... возможно, потому что я нажал ??
Это не позволяло мне толкаться, потому что я не считался членом той ветки, где, как я думал, я был.
Я не хотел ничего менять в своей истории или собирать вишню, и я просто потратил около 8 недель, работая над веткой, так что
Решение заключалось в следующем:
git branch -f myStuckBranch HEAD
git checkout myStuckBranch
Вам нужно выполнить проверку, даже если HEAD и myStuckBranch теперь указывают на одно и то же, потому что вы все еще считаете себя в состоянии отдельной головы (не в ветке)
Я не эксперт в git (в основном использовал mercurial, который никогда не создавал бы эту странную ситуацию), но я понимаю эту команду так, что она просто говорит «измените myStuckBranch, чтобы он указывал на HEAD».
Я обычно использую эту команду для слияния изменений из мастера после извлечения без необходимости менять местами мой рабочий каталог - в противном случае он пытается использовать старую (неинтересную) версию мастера:
git fetch
git branch -f master origin/master -- err yeah don't just ignore what's been going on remotely - eg point my master at the real master
git merge master -- merge the changes into my local branch
Это немного раздражает, когда приходится делать это все время вручную, но все же лучше, чем менять рабочий каталог только для того, чтобы обновить другую ветку, чтобы объединить изменения из нее.
Этот подход потенциально может отбросить часть истории коммитов, но это проще в случае, если слияние старой главной ветки и текущего статуса сложно, или вы просто не против потерять часть истории коммитов.
Чтобы просто сохранить все как есть, без слияния, превратив текущий отсоединенный HEAD в главную ветку:
- Вручную сделайте резервную копию репозитория, если что-то пойдет не так.
- Зафиксируйте последние изменения, которые хотите сохранить.
- Создайте временную ветку (назовем ее
detached-head
), который будет содержать файлы в их текущем состоянии:
git checkout -b detached-head
- (a) Удалите основную ветку, если вам не нужно ее хранить
git branch -D master
- (б) ИЛИ переименуйте, если хотите сохранить
git branch -M master old-master
- Переименуйте временную ветку как новую главную ветку
git branch -M detached-head master
Гит сказал мне, как это сделать.
если вы набрали:
git checkout <some-commit_number>
Сохранить статус
git add .
git commit -m "some message"
Затем:
git push origin HEAD:<name-of-remote-branch>
Git: вы сейчас не в ветке.
Время от времени Git показывает:
Чтобы отправить историю, ведущую к текущему (отсоединенному) состоянию HEAD, используйте
git push origin HEAD:<name-of-remote-branch>
Это значит :
Чтобы исправить это, выполните 2 команды:
Это сбивало меня с толку, когда я начал работать с git, и позже я понял, почему это происходит и как лучше всего поступить в такой ситуации.
Основная причина такого возникновения заключается в том, что обычно git HEAD всегда указывает на какую-то ветку, и когда вы пытаетесь указать HEAD на какой-то конкретный коммит, вы переводите HEAD в состояние detached HEAD .
Когда HEAD подключен к состоянию -
cat .git/HEAD # output--> ref: refs/heads/master or ref: refs/heads/main
Когда HEAD находится в отсоединенном состоянии -
cat .git/HEAD # output--> b96660a90cad75867453ebe1b8d11754bbb68b0e <commit hash>
Решение -
git stash # Temporarily shelves (or stashes) changes
git branch # Find your default branch
git switch master # Point HEAD to master or main branch
git stash pop # Apply all the changes you had previously
Как обычно HEAD
указывает на ветку. Когда он не указывает на ветку вместо этого, когда он указывает на хеш фиксации, например69e51
это означает, что у вас есть отдельная ГОЛОВА. Вам нужно указать две ветки, чтобы исправить проблему. Вы можете сделать две вещи, чтобы исправить это.
- git checkout other_branch // Невозможно, когда вам нужен код в этой фиксации
hash
- создайте новую ветку и укажите хеш фиксации на только что созданную ветку.
HEAD должен указывать на ветку, а не хеш фиксации - золотое правило.
Я пришел сюда, потому что у меня былоHEAD detached at...
сообщение.
В моем случае это не было связано с какими-то локальными изменениями, потому что в этой системе я никогда не делал никаких изменений.
Причина моего сообщения была: я случайно выписался.origin/myBranch
вместо .
Поэтому при выездеmyBranch
все пришло в норму.
Понимая, что у меня оторвалась голова, не зная, как мне это удалось (примерно через три коммита), я также обнаружил, что пытаясь merge
, rebase
или cherry-pick
вызвал сотни конфликтов слияния, поэтому я выбрал другой подход:
(Предполагая, что все зафиксировано (рабочее дерево "чистое"))
Сохраните мои сообщения о фиксации:
git log > /tmp/log
Сохраните мое рабочее дерево:
mkdir /tmp/backup && cp -a all_my files_and_directories /tmp/backup
Вернуться к
master
:git checkout master
Удалите все рабочие файлы и каталоги:
rm ...
Используйте резервную копию:
cp -a /tmp/backup/. .
git add
а такжеgit commit
используя сообщения из сохраненных/tmp/log
, возможно, повторяя это с разными подмножествами файлов...
Недостатком является то, что вы теряете историю коммитов, если один файл изменялся несколько раз с тех пор, как master
, но в итоге у меня был чистый master
.
Когда вы находитесь в ситуации отсоединения головы и создали новые файлы, сначала убедитесь, что эти новые файлы добавлены в индекс, например с помощью:
git add .
Но если вы только изменили или удалили существующие файлы, вы можете добавить (-a) и зафиксировать сообщение (-m) одновременно с помощью:
git commit -a -m "my adjustment message"
Затем вы можете просто создать новую ветку с вашим текущим состоянием с помощью:
git checkout -b new_branch_name
У вас будет новая ветка, и все ваши настройки будут в этой новой ветке. Затем вы можете продолжить нажимать на пульт и / или оформить заказ / вытащить / объединить, как вам угодно.
Я хотел сохранить свои изменения так, я просто исправляю это, делая...
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
это работа для меня
Отсоединенный HEAD означает, что вы в настоящее время не находитесь ни в одной ветке. Если вы хотите СОХРАНИТЬ свои текущие изменения и просто создать новую ветку, вы делаете следующее:
git commit -m "your commit message"
git checkout -b new_branch
Впоследствии вы потенциально можете объединить эту новую ветку с другими ветвями. Всегда полезна команда git "собака":
git log --all --decorate --oneline --graph
Если вы ненавидите head и вместо этого хотите вернуться к main:
git checkout main
Если вам нравится head, но вы просто хотите, чтобы main отслеживал его:
git checkout -B main HEAD
(Это работает с любым именем ветки, а не толькоmain
, и для любого указателя фиксации, а не толькоHEAD
.)
Это работает для меня, он назначит новую ветку для отдельной головы:
git checkout new_branch_name detached_head_garbage_name
git pull origin master
работал на меня. Речь шла просто о явном указании удаленного имени и имени филиала.
С помощью git rebase вы можете переместить ГОЛОВУ в желаемый коммит.
Предположим, у вас есть ветка в обособленном состоянии, например:
* bfcb8f9 Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 (HEAD -> master) Commit 2 --amend
|/
* 1818f91 Commit 1
Отсоединенная голова была создана путем перебазирования по ошибке, указывая на отсоединенную фиксацию, которая была создана ранее с помощью команды git commit --amend .
Если вы хотите переместить ссылку HEAD на самую последнюю фиксацию, примените перебазирование с желаемой фиксацией HASH, на которую вы хотите указать. В этом примере хеш - это самая последняя фиксация:
git rebase bfcb8f9
и это оставит вашу ветку с HEAD, указывающей на желаемый коммит (в данном случае самый последний):
* bfcb8f9 (HEAD -> master) Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2 --amend
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 Commit 2
|/
* 1818f91 Commit 1