Перейти к основному содержимому

Понимание Detached HEAD в Git

· 6 мин. чтения

Задача: Наибольшая подстрока без повторений

Для заданной строки s, найдите длину наибольшей подстроки без повторяющихся символов. Подстрока — это непрерывная непустая последовательность символов внутри строки...

ANDROMEDA 42

1. Обзор

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

В этом уроке мы обсудим, что такое отсоединенный HEAD и как он работает. Мы рассмотрим, как переходить в отдельный HEAD в Git и выходить из него.

2. Что такое HEAD в Git

Git сохраняет запись о состоянии всех файлов в репозитории, когда мы создаем коммит. HEAD — еще один важный тип ссылки. Целью HEAD является отслеживание текущей точки в репозитории Git . Другими словами, HEAD отвечает на вопрос «Где я сейчас?»:

$git log --oneline
a795255 (HEAD -> master) create 2nd file
5282c7c appending more info
b0e1887 creating first file

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

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

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

3. Пример отдельной ГОЛОВКИ

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

./349b74dd60a49965d6e97ed067442796.png

Как мы видим, HEAD указывает на ветку master, которая указывает на последний коммит. Все выглядит идеально. Однако после выполнения приведенной ниже команды репо находится в отдельном HEAD:

$ git checkout 5282c7c
Note: switching to '5282c7c'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

git switch -c <new-branch-name>

Or undo this operation with:

git switch -

HEAD is now at 5282c7c appending more info

users@ubuntu01: MINGW64 ~/git/detached-head-demo ((5282c7c...))

Ниже приведено графическое представление текущего git HEAD. Поскольку мы проверили предыдущий коммит, теперь HEAD указывает на коммит 5282c7c , а ветка master по-прежнему ссылается на то же самое:

./a6821ce3bb1a6bb09b9f8923b70fedba.png

4. Преимущества Git Detached HEAD

После отсоединения HEAD путем проверки определенного коммита ( 5282c7c) мы можем перейти к предыдущему моменту в истории проекта.

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

Что, если бы мы могли не только взглянуть на прошлое, но и изменить его? Вот что позволяет нам сделать отдельный HEAD. Давайте рассмотрим, как это сделать, используя следующие команды:

echo "understanding git detached head scenarios" > sample-file.txt
git add .
git commit -m "Create new sample file"
echo "Another line" >> sample-file.txt
git commit -a -m "Add a new line to the file"

Теперь у нас есть два дополнительных коммита, которые происходят от нашего второго коммита. Запустим git log –oneline и посмотрим на результат:

$ git log --oneline
7a367ef (HEAD) Add a new line to the file
d423c8c create new sample file
5282c7c appending more info
b0e1887 creating first file

Прежде чем HEAD указывал на коммит 5282c7c , мы добавили еще два коммита, d423c8c и 7a367ef . Ниже представлено графическое представление коммитов, сделанных поверх HEAD. Это показывает, что теперь HEAD указывает на последний коммит 7a367ef :

./e7181ffa51458dd2421de03685ab1159.png

Что нам делать, если мы хотим сохранить эти изменения или вернуться к предыдущему? Посмотрим в следующем пункте.

5. Сценарии

5.1. Случайно

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

git switch <branch-name>

 

git checkout <branch-name>

5.2. Внесены экспериментальные изменения, но их нужно отменить

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

5.3. Внесены экспериментальные изменения, но необходимо их сохранить

Если мы хотим сохранить изменения, сделанные с помощью отдельного HEAD, мы просто создаем новую ветку и переключаемся на нее. Мы можем создать его сразу после получения отдельного HEAD или после создания одного или нескольких коммитов . Результат тот же. Единственное ограничение состоит в том, что мы должны сделать это до того, как вернемся к нашей обычной ветке. Давайте сделаем это в нашем демонстрационном репозитории, используя приведенные ниже команды после создания одного или нескольких коммитов:

git branch experimental
git checkout experimental

Мы можем заметить, что результат git log –oneline точно такой же, как и раньше, с той лишь разницей, что имя ветки указано в последнем коммите:

$ git log --oneline
7a367ef (HEAD -> experimental) Add a new line to the file
d423c8c create new sample file
5282c7c appending more info
b0e1887 creating first file

6. Заключение

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