$ sudo teach IT
Модуль 3 · Отмена и .gitignore · Урок 3.2

Отмена изменений

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

Теория + практика~25 минутНовичокrestorecommit --amend

Вернуть файл как в последнем коммите

Чтобы отменить изменения в файле, которые вы ещё не закоммитили, используйте git restore <файл>: команда возвращает файл к сохранённой версии, и все правки пропадают. Разберём три ситуации: правка получилась неудачной, в индекс попало лишнее, а в только что сделанном коммите опечатка или не хватает файла. Раньше git status подсказывал нужные команды, но мы только читали подсказки и шли дальше, а теперь пора ими пользоваться.

Простыми словами

Это как «вернуть к сохранённому» в игре: вы пробовали что-то рискованное, не понравилось, и файл снова такой, каким был при последней фиксации. Только у такой «загрузки» нет второй попытки, и это важно запомнить сразу.

Официальный термин и пример

Команда git restore (restore — «восстановить») возвращает файлы рабочей папки к сохранённой версии. Допустим, вы экспериментировали и случайно испортили заголовок в index.html:

Терминал
$ git status
On branch main
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:   index.html

no changes added to commit (use "git add" and/or "git commit -a")
$ git diff
diff --git a/index.html b/index.html
index 5b596b8..6025cc0 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,7 @@
   <link rel="stylesheet" href="style.css">
 </head>
 <body>
-  <h1>Алекс Иванов</h1>
+  <h1>Алекс Иванов??</h1>
   <p class="lead">Начинающий веб-разработчик</p>
   <section id="about">
     <h2>Обо мне</h2>
$ git restore index.html
$ git status
On branch main
nothing to commit, working tree clean

Разбор по строкам

  • modified: index.html и подсказка use "git restore <file>..." to discard changes — Git сам называет команду для отмены. Слово discard значит «отбросить».
  • git diff показывает, что именно пропадёт: лишние знаки вопроса в заголовке. Перед отменой на него стоит взглянуть.
  • git restore index.html — команда молчит, как и большинство команд Git при успехе.
  • working tree clean — файл снова совпадает с последним коммитом, а заголовок прежний.

Корзины нет

Правки, отброшенные через git restore, пропадают насовсем: Git никогда их не сохранял, ведь они не были закоммичены. Прежде чем отменять, посмотрите git diff. И не пишите git restore ., если не уверены: точка означает «все файлы сразу».

Убрать файл из индекса

Вторая ситуация: вы выполнили git add . и вместе с нужным файлом подготовили к коммиту лишний. Правки в файле жалко не терять, нужно лишь снять файл с «сцены» (индекса). Допустим, вы дописали строку в README.md и поэкспериментировали со стилями, а git add . взял всё сразу:

Терминал
$ git add .
$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   README.md
	modified:   style.css

$ git restore --staged style.css
$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   README.md

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:   style.css

Разбор по строкам

  • use "git restore --staged <file>..." to unstage — подсказка Git: unstage значит «снять с подготовки». Флаг --staged говорит, что действовать нужно на индекс, а не на рабочую папку.
  • После git restore --staged style.css файл ушёл в раздел Changes not staged for commit. Правка в нём сохранилась: мы лишь передумали включать её в коммит.
  • README.md остался в индексе, и в следующий коммит пойдёт только он.

Если эксперимент в style.css вам не нужен совсем, теперь можно отбросить и его — первой командой из этого урока:

Терминал
$ git restore style.css

Различие запомните по одной мысли: без флага git restore меняет файл на диске (правки пропадают), с --staged — только индекс (правки остаются).

КомандаЧто происходитПравки в файле
git restore файлфайл на диске становится таким же, как в индексе (а если файл не добавляли — как в последнем коммите)пропадают
git restore --staged файлфайл убирается из индекса, то есть из будущего коммитаостаются

Откуда два разных совета в git status

До первого коммита git status советовал убрать файл из индекса командой git rm --cached: тогда ещё не было коммита, с которым можно сравнить. После первого коммита подсказка заменяется на git restore --staged. Смысл один: снять файл с подготовки.

Поправить последний коммит: git commit --amend

Третья ситуация случается постоянно: коммит сделан, и тут же видно опечатку в подписи или забытый файл. Делать для этого новый «исправляющий» коммит не обязательно. Это как переклеить ярлык на только что запакованной коробке или доложить в неё забытую вещь. Команда git commit --amend (amend — «исправить», «дополнить») заменяет последний коммит новым.

Опечатка в сообщении

Допустим, вы добавили в README строку «Страница на чистом HTML и CSS, без фреймворков.» и закоммитили её с опечаткой в подписи:

Терминал
$ git commit -m "Добавить описанеи сайта"
[main 0ca1cfc] Добавить описанеи сайта
 1 file changed, 2 insertions(+)
$ git commit --amend -m "Добавить описание сайта"
[main 1dbd335] Добавить описание сайта
 Date: Tue Nov 10 13:00:00 2026 +0300
 1 file changed, 2 insertions(+)
$ git log --oneline
1dbd335 (HEAD -> main) Добавить описание сайта
12d081f Добавить .gitignore
284ecf7 Исправить опечатку в заголовке

Разбор по строкам

  • --amend -m "…" — заменить подпись последнего коммита новым текстом. Если написать просто git commit --amend, откроется редактор со старой подписью: исправьте её, сохраните и закройте окно.
  • [main 1dbd335] — хеш другой, не 0ca1cfc. Коммит не «отредактирован»: Git создал новый, а старый отложил в сторону. Именно поэтому хеш меняется.
  • Date: — дата исходного коммита; эта строка при amend появляется нормально.
  • В git log коммит с опечаткой не виден: на его месте стоит исправленный.

Забытый файл

Вы вспомнили, что к тому же коммиту относится ещё одна правка: описание сайта для поисковиков в <head> файла index.html. Добавьте в index.html после строки с <title> такую строку:

HTML · index.html
  <meta name="description" content="Визитка Алекса Иванова, начинающего веб-разработчика">

Подготовьте файл и допишите его в последний коммит, подпись при этом оставив прежней:

Терминал
$ git add index.html
$ git commit --amend --no-edit
[main 746ac3d] Добавить описание сайта
 Date: Tue Nov 10 13:00:00 2026 +0300
 2 files changed, 3 insertions(+)

Разбор по строкам

  • git add index.html — обычная подготовка файла: amend берёт то, что лежит в индексе.
  • --no-edit — не открывать редактор и не менять сообщение.
  • 2 files changed, 3 insertions(+) — теперь в коммите два файла: README.md и index.html. Хеш снова новый: 746ac3d.

Amend переписывает историю: только для своего и неопубликованного

Amend подменяет коммит новым с другим хешем. Пока коммит живёт только на вашем компьютере, это безопасно. Но если вы уже отправили его кому-то (отправлять код на GitHub мы скоро научимся), у других людей останется старый коммит, и ваши истории разойдутся. Поэтому правило такое: amend — только для последнего коммита, которым ещё ни с кем не поделились.

Восстановить удалённый файл

Удалили файл по ошибке или скрипт стёр лишнее? Пока удаление не закоммичено, Git помнит файл. Попробуйте: удалите style.css из папки проекта и посмотрите на статус.

Терминал
$ rm style.css
$ git status
On branch main
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	deleted:    style.css

no changes added to commit (use "git add" and/or "git commit -a")
$ git restore style.css
$ git status
On branch main
nothing to commit, working tree clean

deleted: style.css — Git видит, что отслеживаемый файл исчез, и предлагает ту же самую git restore. Она ведёт себя так: «файла нет, значит, достать его заново из сохранённой версии». Если же файл был удалён уже давно и удаление закоммичено, достать его можно из прошлого коммита; об этом — в следующем уроке.

В старых статьях и ответах

В статьях до 2019 года вы встретите git checkout -- файл вместо git restore файл и git reset HEAD файл вместо git restore --staged файл. Это то же самое, старые команды по-прежнему работают. В курсе мы используем новые: у них понятнее названия.

Практика у себя

Пройдём все три ситуации подряд на визитке. После каждого шага сверяйтесь с git status.

  1. Старт. В ~/projects/portfolio выполните git status (должно быть working tree clean) и git log --oneline (шесть коммитов, последний — «Добавить .gitignore»).
  2. Испортите и отмените. В index.html допишите после «Алекс Иванов» в заголовке h1 два знака вопроса и сохраните. Выполните git diff, затем git restore index.html. Ожидаем: git status снова чистый, в заголовке нет знаков вопроса.
  3. Две правки, одна лишняя. Дополните README.md строкой Страница на чистом HTML и CSS, без фреймворков. через пустую строку после уже имеющейся. В style.css замените color: #222; на color: hotpink;. Сохраните оба файла.
  4. Всё в индекс, лишнее обратно. Выполните git add ., затем git restore --staged style.css и git status: README.md в индексе, style.css изменён, но не подготовлен. Эксперимент не нужен: git restore style.css. Теперь git status показывает только README.md в разделе Changes to be committed.
  5. Коммит с опечаткой. Сделайте git commit -m "Добавить описанеи сайта" (опечатка намеренная), затем исправьте: git commit --amend -m "Добавить описание сайта".
  6. Забытая правка. Добавьте в index.html строку с <meta name="description"…> из раздела про amend, затем git add index.html и git commit --amend --no-edit. Проверьте: git show --stat перечисляет два файла.
  7. Удалите и верните. rm style.css, git status (должно быть deleted: style.css), git restore style.css. Файл на месте.

Итог (хеши у вас будут другие):

Терминал
$ git log --oneline
746ac3d (HEAD -> main) Добавить описание сайта
12d081f Добавить .gitignore
284ecf7 Исправить опечатку в заголовке
cb00bb8 Добавить раздел «Мои проекты»
f58d529 Добавить README
8c23940 Добавить стили
027a150 Добавить главную страницу

Проверьте себя

  • git log --oneline показывает семь коммитов, последний — «Добавить описание сайта», без следов опечатки в подписи.
  • git status сообщает nothing to commit, working tree clean; style.css на месте и без hotpink.
  • git show --stat перечисляет в последнем коммите README.md и index.html.
  • Вы можете объяснить, чем git restore файл отличается от git restore --staged файл.

Частые ошибки

error: pathspec '…' did not match any file(s) known to git. Git не нашёл такого файла среди отслеживаемых: опечатка в имени либо файл новый и никогда не попадал в коммит. Для нового файла restore бессилен, потому что восстанавливать нечего. Такой файл удаляют руками.

Вы отменили правку, а она нужна. Если команда была git restore файл без коммита, вернуть правки нельзя. В следующий раз смотрите git diff до отмены.

Перепутали --staged и без него. Хотели снять файл с подготовки, но написали git restore файл, и правки пропали. Хотели отбросить правки, но написали с --staged — ничего страшного: файл просто ушёл из индекса, а правки остались. Если сомневаетесь, начинайте с --staged.

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

Что важно запомнить

  • git restore <файл> отбрасывает правки в файле до сохранённой версии, без корзины; сначала смотрите git diff.
  • git restore --staged <файл> снимает файл с подготовки к коммиту, правки остаются.
  • git commit --amend -m "…" меняет подпись последнего коммита, git add + git commit --amend --no-edit дописывает в него забытое. Хеш при этом меняется.
  • Amend допустим только для последнего коммита, которым вы ни с кем не поделились.
  • Удалённый файл возвращается той же git restore <файл>. В старых статьях вместо неё встречаются checkout -- файл и reset HEAD файл.

Всё это работало для последнего коммита и для правок, которые ещё не закоммичены. А как вернуться на несколько коммитов назад, посмотреть прошлое проекта и отменить старый коммит, не ломая остальную историю? Об этом — в следующем уроке.

Подробно — в документации: git restore, git commit (раздел про --amend).

На следующий урок