Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос нашим менторам. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Отмена коммитов

Гит — система, в которой не нужно бояться совершать ошибки. Можно сказать, что это единственный способ научиться им пользоваться. В git практически всегда есть способ восстановить или изменить любые коммиты. На крайний случай спасет повторный git clone.

Что делать, если коммит уже сделан, но он нас по каким-то причинам не устраивает? Ситуаций может быть много, и все они возникают регулярно даже у профессиональных разработчиков:

  • Забыли добавить в коммит нужные файлы
  • Изменения нужно «откатить», чтобы доработать
  • Изменения больше не актуальны, и их нужно удалить
  • Изменения были сделаны по ошибке, и их нужно отменить

Git по большей части система «только вперёд». Правильный подход при работе с гитом — создание нового, а не изменение старого. Все ситуации, описанные выше, можно решить новым коммитом, изменяющим код в нужном направлении. Это не только удобно, но и безопасно. Изменение истории коммитов — операция опасная и чревата проблемами при синхронизации с удалёнными репозиториями. Об этом мы поговорим позже.

Несмотря на сказанное выше, внутри git существуют специальные команды, позволяющие упростить отмену либо изменение коммита. С их помощью можно сделать историю коммитов понятной, а сам процесс «отката» быстрым.

Git revert

Самая простая ситуация — отмена изменений. Фактически она сводится к созданию ещё одного коммита, который выполняет изменения противоположные тому коммиту, который отменяется. Руками создавать подобный коммит довольно сложно, поэтому в git добавили команду, автоматизирующую откат. Эта команда называется git revert:

# Этой команде нужен идентификатор коммита
# Это коммит, которым мы удалили файл PEOPLE.md
hexlet-git$: git revert aa600a43cb164408e4ad87d216bc679d097f1a6c
# После этой команды откроется редактор, ожидающий ввода описания коммита
# Обычно сообщение revert не меняют, поэтому достаточно просто закрыть редактор
[master 65a8ef7] Revert "remove PEOPLE.md"
 1 file changed, 1 insertion(+)
 create mode 100644 PEOPLE.md
# В проект вернулся файл PEOPLE.md

hexlet-git$ git log -p

commit 65a8ef7fd56c7356dcee35c2d05b4400f4467ca8
Author: tirion <tirion@got.com>
Date:   Sat Sep 26 15:32:46 2020 -0400

    Revert "remove PEOPLE.md"

    This reverts commit aa600a43cb164408e4ad87d216bc679d097f1a6c.

diff --git a/PEOPLE.md b/PEOPLE.md
new file mode 100644
index 0000000..4b34ba8
--- /dev/null
+++ b/PEOPLE.md
@@ -0,0 +1 @@
+Haskell Carry

Команда revert "отменяет" не только последний коммит, но и любой другой коммит из истории проекта. Согласитесь, это очень круто. Без системы контроля версий о таком нельзя было и мечтать.

Git reset

Иногда удалить нужно только что сделанный по ошибке коммит. Конечно, и в этом случае подходит git revert, но так загрязняется история. Если этот коммит сделан был только сейчас и ещё не отправлялся на Github, то лучше сделать так, как будто бы этого коммита не существовало в принципе.

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

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

Для удаления коммита используется команда git reset. Делается это так:

# добавляем новый коммит, который мы сразу же удалим
hexlet-git$ echo 'test' >> INFO.md
hexlet-git$ git add INFO.md
hexlet-git$ git commit -m 'update INFO.md'
[master 17a77cb] update INFO.md
 1 file changed, 1 insertion(+)
 # Важно, что мы не делаем git push

 hexlet-git$ git reset --hard HEAD~
 HEAD is now at 65a8ef7 Revert "remove PEOPLE.md"

# Если посмотреть git log, то последнего коммита там больше нет

git reset — мощная команда, имеющая множество различных флагов и способов работы. С её помощью удаляются или отменяются (без удаления) коммиты, восстанавливаются файлы из истории и так далее. Работа с ней относится к продвинутому использованию git, здесь же мы затрагиваем только самую базу.

Флаг --hard означает полное удаление. Без него git reset отменит коммит, но не удалит его, а поместит все изменения этого коммита в рабочую директорию, так что с ними можно будет продолжить работать. HEAD~ означает "один коммит от последнего коммита". Если бы мы хотели удалить два последних коммита, то могли бы написать HEAD~2.

HEAD (голова) — так обозначается последний сделанный коммит. Подробнее эту терминологию мы разберем в уроке, посвященном внутреннему устройству git.

Если не указывать флаг --hard, то по умолчанию подразумевается флаг --mixed. В таком варианте reset отправляет изменения последнего коммита в рабочую директорию. Затем их можно исправить или отменить и выполнить новый коммит.

hexlet-git$ echo 'no code no pain' > README.md
hexlet-git$ git add README.md
hexlet-git$ git commit -m 'update README.md'
[master f85e3a6] update README.md
 1 file changed, 1 insertion(+)

# Теперь откатываем последний коммит
hexlet-git$ git reset HEAD~
Unstaged changes after reset:
M   README.md

hexlet-git$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   README.md

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

Самостоятельная работа

  1. Выполните все шаги из урока
  2. Измените добавленный текст на No code No pain и закоммитьте его с сообщением "update README.md"
  3. Залейте изменения на Github

<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят менторы из команды Хекслета или другие студенты.

Зарегистрироваться

или войти в аккаунт

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

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».