Урок курса

Добавил не тот файл: убрать из индекса

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 "Правка". Какой результат ожидается?

Выберите один вариант
Без регистрации · результат не сохраняется

Продолжить с сохранением прогресса

Перейдите к уроку в учебном кабинете.

Перейти к интерактивному уроку