15. Удаление коммитов из ветки
Цели
- Научиться удалять самые последние коммиты из ветки.
revert
из предыдущего раздела является мощной командой, которая позволяет отменить любые коммиты в репозиторий. Однако, и оригинальный и «отмененный» коммиты видны в истории ветки (при использовании команды git log
).
Часто мы делаем коммит, и сразу понимаем, что это была ошибка. Было бы неплохо иметь команду «возврата», которая позволила бы нам сделать вид, что неправильного коммита никогда и не было. Команда «возврата» даже предотвратила бы появление нежелательного коммита в истории git log
.
01 Команда reset
Мы уже видели команду reset
и использовали ее для согласования области подготовки с выбранным коммитом (в предыдущем уроке мы использовали коммит HEAD
).
Если выполнить команду reset
с указанием ссылки на коммит (т.е. метки HEAD
, имени ветки или тега, хеша коммита), то команда...
- Изменит текущую ветку, чтобы она указывала на указанный коммит.
- Опционально сбросит область подготовки до соответствия с указанным коммитом.
- Опционально сбросит рабочую директорию до соответствия с указанным коммитом.
02 Проверьте нашу историю
Давайте сделаем быструю проверку нашей истории коммитов.
Выполните
git log
Результат
$ git log
86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (HEAD -> main) [Alexander Shvets]
6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets]
b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]
Мы видим, что два последних коммита в этой ветке - «Oops» и «Revert Oops». Давайте удалим их с помощью сброса.
03 Для начала отметьте эту ветку
Но прежде чем удалить коммиты, давайте отметим последний коммит тегом, чтобы потом можно было его найти.
Выполните
git tag oops
Результат
$ git log
86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (HEAD -> main, tag: oops) [Alexander Shvets]
6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets]
b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]
04 Сброс к коммиту, предшествующему oops
Глядя на историю лога (см. выше), мы видим, что коммит с тегом v1
является коммитом, предшествующим ошибочному коммиту. Давайте сбросим ветку до этой точки. Поскольку ветка имеет тег, мы можем использовать имя тега в команде сброса reset
(если она не имеет тега, мы можем использовать хеш коммита).
Выполните
git reset --hard v1
git log
Результат
$ git reset --hard v1
HEAD is now at b7614c1 Added HTML header
$ git log
b7614c1 2023-11-28 | Added HTML header (HEAD -> main, tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]
Наша ветка main
теперь указывает на коммит v1
, а коммитов "Revert Oops" и "Oops" в ветке уже нет. Параметр --hard
указывает, что рабочая директория должна быть приведена к тому состоянию, которое соответствует HEAD
-коммиту ветки.
05 Ничего никогда не теряется
Что же случается с ошибочными коммитами? Оказывается, что коммиты все еще находятся в репозитории. На самом деле, мы все еще можем на них ссылаться. Помните, в начале этого урока мы создали для отмененного коммита тег oops
? Давайте посмотрим на все коммиты.
Выполните
git log --all
Результат
$ git log --all
b7614c1 2023-11-28 | Added HTML header (HEAD -> main, tag: v1) [Alexander Shvets]
86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (tag: oops) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]
Мы видим, что ошибочные коммиты не исчезли. Они все еще находятся в репозитории. Просто они отсутствуют в ветке main
. Если бы мы не отметили их тегами, они по-прежнему находились бы в репозитории, но не было бы никакой возможности ссылаться на них, кроме как при помощи хешей этих коммитов. Коммиты, на которые нет ссылок, остаются в репозитории до тех пор, пока не будет запущен сборщик мусора.
06 Опасность сброса
Сброс в локальных ветках, как правило, безопасен. Последствия любой «аварии» как правило, можно восстановить простым сбросом с помощью нужного коммита.
Однако, если ветка уже стала общедоступной на удаленных репозиториях, сброс может сбить с толку других пользователей ветки.