Как я могу согласовать отдельную ГОЛОВКУ с мастером / происхождением? - PullRequest
1436 голосов
/ 24 апреля 2011

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

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

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

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

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

Ответы [ 26 ]

2375 голосов
/ 24 апреля 2011

Во-первых, давайте уточним что такое 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
    Это то, что значит быть «символическим реф»,Он указывает на объект через какую-то другую ссылку.
    (Символические ссылки изначально были реализованы как символические ссылки, но позже были заменены простыми файлами с дополнительной интерпретацией, чтобы их можно было использовать на платформах, которые не имеют символических ссылок.)

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

Когда HEAD отсоединен, он указывает непосредственно на коммит, а не косвенно указывает на него через ветвь.Вы можете думать об отделенной 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, вам просто нужно следить за тем, что вы делаете, чтобы не выискивать выпавшую историю из рефлога.


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

587 голосов
/ 18 сентября 2013

Просто сделайте это:

git checkout master

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

git checkout -b temp
git checkout -B master temp
118 голосов
/ 02 августа 2013

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

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

Я подумал: ах-ха! Если HEAD является символическим именем для фиксации текущего заказа, я могу согласовать его с master, перебазировав его по 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.

80 голосов
/ 24 апреля 2011

Ищите здесь основное объяснение отсоединенной головы:

http://git -scm.com / документы / ГИТ-контроль

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

git branch

или

git branch -a

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

* (no branch)
master
branch1

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

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

Вы находитесь в состоянии «отсоединенная ГОЛОВА». Вы можно осмотреться, сделать экспериментальную изменить и зафиксировать их, и вы можете отменить любые коммиты, которые вы делаете в этом состояние, не влияя ни на какие ветви выполнив еще одну проверку.

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

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, чтобы продолжить. Это гарантировало бы, что вы никогда не входите в отдельную ГОЛОВУ.

31 голосов
/ 20 мая 2013

Получите ваш отдельный коммит в его собственную ветку

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

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

21 голосов
/ 08 ноября 2013

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

git checkout origin/develop

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

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

1012 * тогда *

git checkout -b develop

Работает :)

17 голосов
/ 17 сентября 2015

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

git push origin HEAD:master

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


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

git rebase HEAD master
git checkout master

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

10 голосов
/ 08 ноября 2014

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

git branch temp
git checkout master
git merge temp

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

9 голосов
/ 07 января 2018

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

git push origin HEAD:master
git checkout master        
git pull

Первый переводит отсоединенную ГОЛОВУ в удаленное место.

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

Третий восстанавливает ГОЛОВКУ, которая присоединяется к мастеру ветвления.

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

8 голосов
/ 01 марта 2016

Если вы полностью уверены, что ГОЛОВА в хорошем состоянии:

git branch -f master HEAD
git checkout master

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

git push -f

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...