linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it works
  • Уроки
  • База знаний
  • Собеседование
home/git/lessons/git-lab-09-1-undo

lesson ── git-labs ── ~22 мин ── 8 шагов

Отмена: reset, revert, reflog

Цель - пройти три способа «отмотать назад» и понять, когда какой применять. reset переписывает историю - подходит для своей локальной ветки. revert создаёт компенсирующий коммит - безопасен на shared ветке. reflog спасает, когда уже всё сломал.

▶ интерактивный sandbox

Поднимется контейнер gitlab/git-base с git, bash, pre-commit. В браузере откроется терминал, можно сразу git init. Каждый шаг проверяется автоматически. Сеть air-gapped, github.com недоступен.

запустить sandbox →

stack ── git · bash · 256 MB RAM · air-gapped · самоуничтожается через 30 мин простоя

Шаги

  1. 01

    Создай репо с пятью коммитами

    bash
    cd /home/student/work
    mkdir -p undo-lab && cd undo-lab
    git init -b main
    for i in 1 2 3 4 5; do
      echo "line $i" >> file.txt
      git add file.txt
      git commit -m "line $i"
    done
    git log --oneline

    Пять коммитов, файл содержит 5 строк. Это полигон для отмен.

    ✓ Пять коммитов на месте.

  2. 02

    Сделай reset --soft на один коммит

    --soft снимает коммит, но оставляет содержимое в index.

    bash
    cd /home/student/work/undo-lab
    git reset --soft HEAD~1       # --soft = только сдвиг ветки, index и working не трогать
    git log --oneline             # лог короче на 1
    git status                    # содержимое снятого коммита - в index

    Лог теперь 4 коммита. Index содержит line 5 - готов перекоммитить с другим сообщением.

    ✓ Коммит снят, изменение в index.

  3. 03

    Сделай reset --mixed - сбросить index

    --mixed (дефолт) также сбрасывает index. Working tree не трогает.

    bash
    cd /home/student/work/undo-lab
    git reset HEAD~1              # без флага = --mixed: ветка + index, working не трогать
    git log --oneline
    git status                    # изменения в working как unstaged

    Лог - 3 коммита. Index пустой. Working содержит line 4 и line 5 как unstaged изменения. Полезно, когда коммит был сделан с ошибочными файлами в index.

    ✓ Index сброшен. Изменения в working.

  4. 04

    Сделай reset --hard - стереть всё

    bash
    cd /home/student/work/undo-lab
    git reset --hard HEAD~1       # --hard = ветка + index + working, всё в HEAD~1
    git log --oneline
    cat file.txt                  # только 2 строки - всё что было сверху, ушло
    git status                    # working tree clean

    Лог - 2 коммита. file.txt содержит только 2 строки. Working tree clean. Все «потерянные» изменения - теперь не видны через log, но...

    подсказка

    Опасно? Да. Но reflog ещё помнит.

    ✓ Хард-reset сделан. История 'кажется' потерянной.

  5. 05

    Восстанови потерянное через reflog

    reflog - локальный журнал перемещений HEAD. Все «удалённые» коммиты ещё там.

    bash
    cd /home/student/work/undo-lab
    git reflog                    # локальный лог всех перемещений HEAD (90 дней)

    Видишь записи HEAD@{0}, HEAD@{1}, и т.д. Это твои недавние позиции. Найди ту, где было 5 коммитов:

    bash
    # HEAD@{n} = "где HEAD был n шагов назад" по reflog
    git reset --hard HEAD@{4}
    git log --oneline             # все 5 коммитов обратно

    Все 5 коммитов вернулись. reflog держит записи 90 дней по умолчанию.

    ✓ Пять коммитов восстановлены. reflog спас.

  6. 06

    Откати коммит через revert (без переписывания истории)

    Допустим коммит line 3 плохой, и он уже запушен другим в shared. Reset тут опасен - переписывание истории. Используй revert.

    bash
    cd /home/student/work/undo-lab
    # awk '{print $1}' = первая колонка `log --oneline`, это short-sha
    SHA=$(git log --oneline | grep 'line 3' | awk '{print $1}')
    git revert --no-edit $SHA     # --no-edit = взять дефолтное сообщение "Revert ..."
    git log --oneline
    cat file.txt                  # line 3 пропала, остальные сохранены

    Лог стал длиннее на коммит (Revert "line 3"). История сохранена, обоим видно, что произошло. file.txt теперь содержит line 1, line 2, line 4, line 5 - без line 3.

    ✓ Revert создал обратный коммит. История не переписана.

  7. 07

    Сравни итог revert vs то, что было бы у reset

    Запомни различие:

    • reset - снимает коммиты из истории. SHA после reset переписаны. На запушенной ветке это срывает работу команды.
    • revert - добавляет новый коммит, отменяющий старый. История растёт, но никакие SHA не меняются.
    bash
    cd /home/student/work/undo-lab
    git log --oneline --graph

    Видишь линейную историю из 6 записей: 5 оригинальных + revert. Никаких "пропавших" SHA.

    ✓ Шесть коммитов. История целая, ошибка отменена.

  8. 08

    Сделай amend и восстанови старую версию через reflog

    Сделай коммит:

    bash
    cd /home/student/work/undo-lab
    echo "extra" >> file.txt
    git add file.txt && git commit -m "add extra"
    git log --oneline | head -1

    Запомни SHA. Сделай amend:

    bash
    git commit --amend -m "add extra (corrected)"   # заменяет HEAD новым коммитом
    git log --oneline | head -1   # SHA другой, сообщение новое

    SHA коммита другой. Старая версия есть в reflog:

    bash
    git reflog | head -5          # верхние 5 записей: видны и commit, и commit (amend)

    Видны обе версии: одна commit:, другая commit (amend):. Если хочешь откатить amend - git reset --hard HEAD@{1}. Финал урока: ты знаешь, как откатить почти всё, что сделал случайно.

    ✓ Amend и reflog отработали. Большинство «потерянного» в Git можно вернуть.

Что ты узнал

reset двигает указатель ветки назад (3 уровня агрессивности). revert создаёт коммит, обратный по содержимому. reflog хранит все позиции HEAD за последние 90 дней - оттуда восстанавливаются даже «удалённые» коммиты.

команды

  • git reset --soft HEAD~1снять коммит, оставить index
  • git reset --hard <sha>переехать на коммит и стереть всё
  • git revert <sha>создать обратный коммит
  • git reflogлог всех позиций HEAD
  • git reset --hard HEAD@{n}восстановить состояние из reflog

концепции

  • · reset переписывает историю, revert добавляет к ней
  • · reflog видит то, что log не видит
  • · хард-reset опасен, но reflog почти всегда спасает

← предыдущая

Merge против rebase: руками на одном репозитории

следующая →

git bisect: найти баг бинарным поиском

Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки