Урок курса
Правка больше не нужна: восстановить файл
Git и GitHub с нуля: бесплатный курс с практикойВ прошлом уроке git restore --staged снимала staged-изменение отслеживаемого файла, возвращая его запись в индексе к HEAD и сохраняя рабочий текст. git restore без этого флага перезаписывает рабочий файл версией текущего индекса и отбрасывает разницу с ней.
Источник git restore: индекс, а не HEAD напрямую
Когда вы выполняете git restore notes.txt без флага --staged, Git берёт версию файла из текущего индекса и перезаписывает ею файл в рабочей папке. Не из последнего коммита, не из HEAD напрямую — именно из индекса.
Это принципиально. HEAD участвует в результате только косвенно: если индекс совпадает с HEAD (то есть git diff --staged выдаёт пустой вывод), то рабочий файл окажется таким же, как в последнем коммите. Но это следствие совпадения, а не прямое обращение к коммиту.
Проверить, чист ли индекс, можно одной командой:
git diff --staged
Пустой вывод означает: записей в индексе, отличающихся от HEAD, нет. В таком состоянии git restore notes.txt и вернёт именно HEAD-версию файла — но только потому, что индекс её и содержит.
Если же в индексе уже лежит staged-версия notes.txt, отличающаяся от HEAD, — git restore notes.txt восстановит рабочий файл именно до этой staged-версии. Это не ошибка команды, это её точное поведение: источник фиксирован, и это всегда индекс.
Сам индекс команда не изменяет. Что там было — то и останется. Меняется только рабочая папка.
Выполнение git restore и проверка результата
Синтаксис команды минимален:
git restore <путь>
Флаг --staged не указывается. Именно его отсутствие определяет, что изменится рабочая папка, а не индекс.
Файл должен быть отслеживаемым, то есть присутствовать в индексе — иначе команда завершится ошибкой.
Создайте новую отдельную учебную папку и откройте в ней терминал. Выполните команды по одной:
git init -b main
git config user.name "Учебный автор"
git config user.email "learner@example.invalid"
В обычном текстовом редакторе создайте notes.txt со строкой «Первая версия», сохраните файл. Затем выполните:
git add notes.txt
git commit -m "init"
git status
В этой папке main содержит один коммит, файл отслеживается, рабочая папка и индекс чисты. Проверьте пустой git diff --staged. В редакторе добавьте в notes.txt строку «Лишняя правка» и сохраните, но add не выполняйте. Также создайте и сохраните draft.txt с любым учебным текстом; в индекс его не добавляйте.
Шаг 1. Смотрим на правку:
git diff
Вывод покажет примерно следующее:
diff --git a/notes.txt b/notes.txt
index ... 100644
--- a/notes.txt
+++ b/notes.txt
@@ -1 +1,2 @@
Первая версия
+Лишняя правка
Это момент явного решения: вы прочитали правку и решили от неё отказаться.
Шаг 2. Сбрасываем рабочий файл:
git restore notes.txt
Команда не выводит ничего — это нормально. Строка «Лишняя правка» исчезла из рабочего файла безвозвратно: Git не сохраняет предыдущий рабочий текст автоматически.
Шаг 3. Проверяем двумя командами.
git diff
Вывод пустой: рабочий файл совпадает с индексом.
git status
Пример вывода:
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
draft.txt
nothing added to commit but untracked files present (use "git add" to track)
Отслеживаемых правок больше нет, но весь status не чистый: untracked-файл остаётся. notes.txt больше не числится в «Changes not staged for commit». draft.txt по-прежнему виден в «Untracked files» — команда его не тронула.
Когда в индексе staged-версия: restore вернёт не HEAD
Предположим, вы уже добавили правку в индекс через git add, а потом продолжили редактировать файл и теперь хотите «вернуть всё как было в коммите». Интуитивно кажется, что git restore notes.txt должен восстановить версию из HEAD. Но это не так.
Команда возьмёт то, что лежит в индексе прямо сейчас — то есть staged-версию, отличающуюся от HEAD. Рабочая правка поверх staged будет выброшена, а staged-версия останется в индексе нетронутой.
Если рабочий файл уже совпадает со staged-версией, git restore notes.txt вообще ничего не изменит — перезаписывать нечего.
Чтобы действительно вернуть файл к состоянию HEAD, нужны два шага:
git restore --staged notes.txt
Эта команда сбросит запись в индексе обратно к HEAD. Затем:
git restore notes.txt
Теперь источник в индексе совпадает с HEAD, и рабочий файл получит именно эту версию.
Перед вторым шагом имеет смысл выполнить git diff, чтобы убедиться, что вы видите и намеренно отбрасываете текущую рабочую правку — она исчезнет без возможности автоматического восстановления.
Граница применимости: неотслеживаемые файлы команде недоступны
git restore <путь> работает только с файлами, у которых есть запись в текущем индексе. Если записи нет — команда не может взять версию «из индекса» и сообщит об ошибке:
error: pathspec 'draft.txt' did not match any file(s) known to git
Это не значит, что файл никогда не существовал в истории. Достаточно того, что в нынешнем индексе его записи нет — и команда отказывается работать.
Важно понять, что git restore notes.txt никак не влияет на соседние untracked-файлы вроде draft.txt. Они остаются на диске ровно в том состоянии, в котором были. Команда точечная: она действует только на указанный путь, и только если он отслеживается.
Поэтому после восстановления notes.txt в git status по-прежнему виден draft.txt в разделе «Untracked files» — именно так и должно быть.
Задача 1
У отслеживаемого report.txt рабочая версия — В, индекс — Б, последний коммит — А. В и Б отличаются. Выполнили только git restore report.txt без флагов. Какая тройка версий получится?
Задача 2
Практика: создайте отдельный репозиторий с базовым коммитом notes.txt известными командами; используйте обе локальные настройки автора и обычный редактор. Измените notes.txt, но не добавляйте правку в индекс. Создайте новый draft.txt, тоже не добавляя его. Проверьте diff, восстановите только notes.txt и проверьте результат. Запишите обычный diff до и после восстановления и status, отдельно проверьте наличие нового draft.txt. Письменно объясните коллеге восстановление из staged-версии и порядок известных команд для возврата именно к HEAD.
Платформа проверяет только ответ ниже; действия в своём репозитории и письменные ответы вы проверяете самостоятельно.
В другом контрольном случае до обычного restore report.txt индекс содержал подготовленную версию Б, а HEAD — А. После restore обычный diff пуст. Что можно утверждать о git diff --staged для report.txt?
Продолжить с сохранением прогресса
Перейдите к уроку в учебном кабинете.
