Урок курса
Добавил не тот файл: убрать из индекса
Git и GitHub с нуля: бесплатный курс с практикойВ прошлом уроке мы убирали файл из отслеживания целиком — через git rm --cached. Сейчас ситуация другая: файл уже отслеживается, в нём есть нужная правка, но она случайно попала в индекс раньше времени. Нужно снять её из staged-состояния, не потеряв ни строчки из рабочего файла.
Что именно меняет снятие staged-изменения
Индекс хранит полный снимок всех отслеживаемых файлов, а не просто список «что изменилось». Когда вы выполняете git add draft.txt, Git копирует текущее содержимое файла в индекс — с этого момента индексная запись draft.txt отличается от той, что зафиксирована в HEAD.
Снятие staged-изменения — это точечная операция: она затрагивает ровно одну запись в индексе и возвращает её к версии из HEAD. Рабочий файл при этом не трогается. Если в репозитории есть другие файлы с prepared-правками — их записи в индексе остаются нетронутыми.
Важное следствие: снятие staged-изменения одного пути не делает весь git diff --staged пустым автоматически. Он станет пустым только тогда, когда ни один другой файл тоже не находится в staged-состоянии. В учебном примере с draft.txt других изменений нет, поэтому после снятия staged diff действительно будет пустым — но это частный случай, а не гарантированный результат команды.
git restore --staged: флаг, синтаксис и требование к HEAD
Команда выглядит так:
git restore --staged <путь>
Флаг --staged определяет, какую область Git нужно изменить. Без него restore работает с рабочим файлом — перезаписывает его содержимым из индекса. С флагом --staged цель меняется: Git берёт версию файла из HEAD и записывает её в индекс, оставляя рабочий файл нетронутым.
Обязательное условие: HEAD должен существовать, то есть в репозитории должен быть хотя бы один коммит. Если коммитов ещё нет, Git не знает, до какого состояния восстанавливать запись в индексе, и выдаст ошибку. В нашем учебном сценарии это условие выполнено — первый коммит с draft.txt уже создан.
При успехе команда ничего не выводит в терминал. Это нормально: Git молчит, если всё прошло штатно. Убедиться в результате нужно через отдельные команды проверки.
Ещё один важный момент: команда не удаляет файл из индекса. draft.txt останется отслеживаемым — просто его индексная запись теперь совпадает с HEAD, и staged-изменение исчезает.
Три команды, которые подтверждают результат
После git restore --staged draft.txt нужно убедиться, что операция сработала именно так, как ожидалось. Три команды дают полную картину.
git status
До снятия статус показывал draft.txt в секции «Changes to be committed». После снятия он перемещается в «Changes not staged for commit». Это значит, что рабочий файл отличается от индекса — правка сохранена — но в коммит она не войдёт.
git diff --staged
Сравнивает индекс с HEAD. После restore --staged индексная запись draft.txt совпадает с HEAD, поэтому вывод будет пустым. Команда не покажет никакого diff — это и есть подтверждение, что staged-изменение снято.
git diff
Сравнивает рабочий файл с индексом. Здесь правка по-прежнему видна: рабочий draft.txt содержит добавленную строку, а индекс — нет. Вывод покажет добавление именно той строки, которую вы вносили.
Создайте новую отдельную учебную папку и откройте в ней терминал. Выполните команды по одной:
git init -b main
git config user.name "Учебный автор"
git config user.email "learner@example.invalid"
В обычном текстовом редакторе создайте draft.txt со строкой «Первый вариант», сохраните файл. Затем выполните:
git add draft.txt
git commit -m "Первый вариант"
git status
В этой папке main содержит один коммит, файл отслеживается, рабочая папка и индекс чисты. В редакторе добавьте вторую строку «Проверить перед коммитом» и сохраните draft.txt; других изменений нет. Команды и сокращённые наблюдения после этой подготовки:
# Подготовка: файл изменён и добавлен в индекс
git add draft.txt
git status
# On branch main
# Changes to be committed:
# modified: draft.txt
# Снимаем
git restore --staged draft.txt
# Проверяем
git status
# On branch main
# Changes not staged for commit:
# modified: draft.txt
git diff --staged
# (нет вывода)
git diff
# diff --git a/draft.txt b/draft.txt
# index ...
# --- a/draft.txt
# +++ b/draft.txt
# @@ -1 +1,2 @@
# Первый вариант
# +Проверить перед коммитом
git diff показывает добавленную строку «Проверить перед коммитом» — она осталась в рабочем файле. Открыв draft.txt в редакторе, вы увидите обе строки: исходную и новую. Ничего не потеряно.
Опасность: restore без --staged перезапишет рабочий файл
Если набрать git restore draft.txt без флага --staged, Git поймёт команду иначе: он возьмёт содержимое draft.txt из индекса и запишет его в рабочий файл.
Это может уничтожить правки, которые ещё не попали в индекс. Представьте ситуацию: вы добавили draft.txt через git add, потом дописали ещё несколько строк в редакторе и не делали повторный add. В этот момент рабочий файл содержит больше, чем индекс. Если сейчас выполнить git restore draft.txt (без --staged), Git перезапишет рабочий файл версией из индекса — те строки, которые вы писали после add, исчезнут без предупреждения.
Для снятия staged-изменения с сохранением рабочего текста флаг --staged обязателен. Без него вы меняете не то, что нужно.
Есть ещё один частный случай: если рабочий файл уже совпадает с индексом, git restore без флага ничего не изменит в рабочей копии, но staged-изменение при этом тоже не снимется — индекс остался прежним. Команда просто ничего не сделает, а вы можете решить, что всё в порядке. Это тихая ловушка: git status покажет, что файл по-прежнему в «Changes to be committed».
Задача 1
У отслеживаемого README.md три версии: рабочая папка — В, индекс — Б, последний коммит — А. HEAD существует; других изменений нет. Выполнили только git restore --staged README.md. Какая тройка версий получится?
Задача 2
Практика: подготовьте отдельный репозиторий известной последовательностью из урока: git init -b main, обе локальные настройки автора, README.md через редактор, add и первый commit. Измените README, подготовьте правку, а затем отмените только её подготовку с сохранением рабочего текста. Запишите команды и результаты status, обычного diff и staged diff до и после снятия подготовки. Письменно объясните коллеге, чем подготовка отличается от коммита и как проверить сохранность рабочей правки.
Платформа проверяет только ответ ниже; действия в своём репозитории и письменные ответы вы проверяете самостоятельно.
В контрольном репозитории уже есть коммит. После restore --staged для единственного изменённого отслеживаемого файла staged diff пуст. Рабочая правка осталась. Без нового add запустили обычный git commit -m "Правка". Какой результат ожидается?
Продолжить с сохранением прогресса
Перейдите к уроку в учебном кабинете.
