Урок курса

Почему add не сохраняет все будущие правки

Git и GitHub с нуля: бесплатный курс с практикой

В прошлом уроке появились три области Git: рабочая папка, индекс и репозиторий. git add переводил файл в индекс, git commit — сохранял снимок. Индекс хранит версию файла на момент git add: более поздняя правка остаётся в рабочей папке и не попадает в следующий коммит автоматически.

Индекс как снимок момента git add

git add не ставит за файлом «слежку» в смысле постоянного отслеживания. Он делает ровно одно: в момент вызова читает содержимое файла и копирует его в индекс. С этого момента индекс хранит самостоятельную копию — не ссылку на файл в рабочей папке, а именно снимок его содержимого.

Если после git add README.md открыть файл и дописать ещё одну строку, в рабочей папке станет одно содержимое, а в индексе — другое. Индекс не знает о новых изменениях. Он остаётся замороженным на том состоянии, которое было в момент вызова команды.

Именно поэтому между git add и git commit лучше проверять git status: он покажет, совпадает ли рабочая папка с тем, что лежит в индексе, или нет.

Три версии одного файла: коммит, индекс, рабочая папка

Рассмотрим конкретный сценарий. Репозиторий уже содержит один коммит с README.md.

Откройте README.md обычным текстовым редактором. Не удаляя прежний текст, добавьте в конце отдельную строку Правка 1 и сохраните файл. В терминале выполните:

git add README.md

Снова откройте README.md и добавьте после первой правки строку Правка 2. Сохраните файл, но повторный git add не выполняйте. В рабочем файле теперь есть обе строки, а в индексе — только первая. Проверьте состояние:

git status

Вывод 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)
        modified:   README.md

README.md фигурирует в обоих разделах одновременно. Это не ошибка — это точное отражение ситуации: файл существует в трёх различных версиях прямо сейчас.

— Последний коммит хранит README.md без обеих правок — то, что было сохранено ранее.

— Индекс хранит версию с «Правкой 1» — снимок, сделанный при git add.

— Рабочая папка содержит файл с обеими правками — то, что видно при открытии файла.

Строка в разделе «Changes to be committed» говорит: индекс отличается от последнего коммита. Строка в разделе «Changes not staged for commit» говорит: рабочая папка отличается от индекса. Git различает эти два расхождения и сообщает о каждом отдельно.

Коммит фиксирует индекс: незакоммиченная правка остаётся в рабочей папке

Когда выполняется git commit, Git берёт содержимое индекса — и только его — и создаёт из него снимок. Рабочая папка в этот момент не читается. Всё, что там есть сверх индекса, просто остаётся нетронутым.

Продолжим предыдущий сценарий:

git commit -m "Добавлена правка 1"
git status

После коммита git status покажет:

On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
        modified:   README.md

«Правка 1» теперь в истории. «Правка 2» по-прежнему только в рабочей папке — не в индексе, не в репозитории. git log --oneline при этом покажет два коммита, а не три и не один.

Здесь возникает типичное заблуждение: «я уже сделал git add README.md, значит, все мои дальнейшие правки этого файла тоже войдут в коммит». Это неверно. git add не подписывает контракт на будущее. Он копирует файл в индекс ровно один раз — в момент вызова. Правка, сделанная после, для Git выглядит так, как будто git add ещё не выполнялся: она в рабочей папке и нигде больше.

Чтобы «Правка 2» попала в следующий коммит, нужно снова выполнить git add README.md — тогда индекс обновится до текущего состояния файла.

Задача 1

В исходном коммите README содержит только заголовок. В рабочий файл дописали строку «Контакт», выполнили git add README.md, затем дописали «Установка» без повторного add и выполнили обычный git commit -m "Add contact".

Обозначения содержимого:
А — только заголовок;
Б — заголовок и «Контакт»;
В — заголовок, «Контакт» и «Установка».

Как распределены версии сразу после успешного коммита, до любых следующих действий?

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

Задача 2

Практика на своём компьютере: начните с учебного репозитория после урока3, в котором один коммит с README. Добавьте первую строку и сохраните файл, подготовьте README в индексе, затем добавьте вторую строку и сохраните. До фиксации письменно предскажите содержимое будущего коммита. Запишите коммит без повторной подготовки, проверьте status и компактную историю. Запишите, совпал ли результат с прогнозом. Если пример этого урока уже выполнен, подготовьте отдельную новую папку по урокам2–3, сохранив прежний репозиторий.

Для самопроверки: ожидаются два коммита, а README остаётся в Changes not staged for commit. Платформа проверяет только ответ ниже; ваш репозиторий и письменный прогноз вы проверяете самостоятельно.

В контрольном опыте ученик вместо этого получил два коммита и чистый статус; рабочий README всё ещё содержит обе строки. Из списка ниже он совершил ровно одно дополнительное действие между второй правкой и коммитом. Какое действие объясняет результат?

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

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

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

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