open atlas
↑ К треку
Git: от нуля до сеньора GIT · 01 · 03

Три области

Каждое изменение в одной из трёх областей: рабочее дерево (файлы, которые ты правишь), область подготовки/индекс (следующий коммит) и репозиторий (история в .git). git add подготавливает, git commit пишет индекс и двигает HEAD, git status показывает, где какое изменение.

GIT Основы ◷ 16 min
Уровень
ОсновыJuniorMiddleSenior

Новички заучивают git add, затем git commit как заклинание из двух слов и никогда не спрашивают, зачем два шага. Другие инструменты просто имеют «сохранить». Этот лишний шаг — самая отличительная идея git, и как только ты увидишь, для чего он, целый класс запутывающих сообщений — «changes not staged for commit», «changes to be committed» — вдруг читается как простой текст.

К концу этого урока ты сможешь назвать три места, где может жить файл в git, сказать, какая команда переносит изменение из одного в следующее, и читать git status как карту того, где именно сейчас находится каждое из твоих изменений.

Цель

После этого урока ты сможешь назвать три области git — рабочее дерево, область подготовки (индекс) и репозиторий — объяснить, что git add подготавливает, а git commit записывает, описать, на что указывает HEAD, и читать вывод git status как карту того, в какой области находится каждое изменение.

1

Изменение отслеживаемого файла может быть в одной из трёх областей. Представь это как три комнаты, через которые проходит изменение:

  • Рабочее дерево (или рабочий каталог) — реальные файлы на диске, которые ты открываешь и правишь. Здесь ты делаешь изменения.
  • Область подготовки, также называемая индексом — зона ожидания, описывающая предлагаемый следующий коммит. Изменение здесь помечено «это войдёт в мой следующий коммит».
  • Репозиторий — закоммиченная история, хранимая в .git. Как только изменение закоммичено, это постоянная история (см. прошлый урок: снимок).

Изменение движется рабочее дерево → подготовка → репозиторий, по одной явной команде на шаг.

2

git add копирует изменение из рабочего дерева в область подготовки. Оно ничего не коммитит; оно помечает, какие изменения ты намерен включить следующими.

git add app.js          # подготовить текущие изменения одного файла
git add .               # подготовить все изменения в этом дереве каталогов

Тонкость, которую стоит усвоить рано: git add подготавливает снимок файла таким, какой он прямо сейчас. Если ты снова правишь app.js после его подготовки, эта более новая правка не подготовлена — индекс по-прежнему держит версию с момента, когда ты запустил add. Рабочее дерево и индекс могут держать две разные версии одного файла одновременно.

3

git commit пишет то, что в области подготовки, как новый коммит и двигает HEAD. Коммит берёт подготовленный снимок — не рабочее дерево — и записывает его как постоянный коммит в репозиторий.

git commit -m "Add login form"

HEAD — это указатель git на «где ты сейчас» — коммит, поверх которого построится твой следующий коммит. После успешного коммита новый коммит становится последним в истории, и HEAD продвигается, чтобы указывать на него. Всё, что ты изменил, но не подготовил, коммит не трогает, и оно остаётся ожидающим изменением в рабочем дереве.

4

git status показывает, в какой области каждое изменение. Это карта, связывающая три области воедино. Он сортирует твои изменения по трём корзинам:

git status
# Changes to be committed:        <- подготовлено (в индексе)
# Changes not staged for commit:  <- правлено в рабочем дереве, ещё не добавлено
# Untracked files:                <- новые файлы, которых git никогда не видел

Читай буквально: «to be committed» = подготовлено, «not staged» = правки рабочего дерева, ждущие git add, «untracked» = файлы, которые существуют на диске, но вообще никогда не добавлялись в git. Запускай его постоянно; он убирает любые догадки о том, что будет содержать твой следующий коммит.

Почему это работает

Зачем вообще нужна область подготовки вместо того, чтобы коммитить рабочее дерево напрямую? Потому что она позволяет собрать коммит из подмножества твоих изменений. Допустим, ты починил баг и заодно переформатировал несвязанный файл. Это должны быть два коммита, а не один мутный. Индекс позволяет подготовить только починку бага, чисто закоммитить её, а затем подготовить и закоммитить форматирование отдельно. Самый острый инструмент для этого — режим патча:

git add -p     # интерактивно подготовить выбранные куски, а не целые файлы

git add -p проводит тебя по каждому изменённому куску и спрашивает, подготавливать ли его — так что даже части одного файла могут уйти в разные коммиты. Область подготовки — это то, что делает возможной опрятную, пригодную к ревью историю вместо сваливания каждой правки в процессе в один ком.

Разбор примера

Две правки, один чистый коммит.

Ты открываешь репозиторий и меняешь два файла: чинишь настоящий баг в auth.js и заодно правишь отступы в README.md. Ты хочешь, чтобы в этот коммит вошла только починка бага.

  1. git status показывает оба под Changes not staged for commit — правлено в рабочем дереве, ничего ещё не подготовлено.
  2. git add auth.js продвигает в область подготовки только починку бага. Запусти git status снова: auth.js теперь под Changes to be committed, а README.md остаётся под Changes not staged for commit. Два файла теперь в двух разных областях.
  3. git commit -m "Fix token refresh bug" пишет подготовленный снимок — только auth.js — как новый коммит, и HEAD продвигается к нему. Изменения README нет в коммите; оно всё ещё ожидающая правка в рабочем дереве, готовая к собственному отдельному коммиту позже.

Область подготовки — это ровно то, что позволило тебе разбить одну рабочую сессию на точный коммит с единственной целью.

Частая ошибка

Классическая ловушка: ты делаешь git add file.js, затем продолжаешь править file.js, затем git commit и ждёшь, что твои последние правки войдут. Не войдут. add захватил файл таким, какой он был в тот миг; правки, сделанные после, живут только в рабочем дереве. Лечение — снова git add перед коммитом (или используй git commit -a, который автоматически подготавливает изменения уже отслеживаемых файлов — но учти, он полностью пропускает неотслеживаемые файлы). Если сомневаешься, git status перед каждым коммитом точно скажет, что подготовлено.

Проверь себя
Викторина

Ты правишь app.js, запускаешь git add app.js, затем снова правишь app.js, затем запускаешь git commit. Что попадёт в коммит?

Итог

Изменение в git живёт в одной из трёх областей: рабочее дерево (файлы, которые ты правишь на диске), область подготовки / индекс (предлагаемый следующий коммит) и репозиторий (закоммиченная история в .git). git add продвигает изменение из рабочего дерева в индекс — захватывая файл таким, какой он в тот миг, — а git commit записывает подготовленный снимок как новый коммит, продвигая HEAD к нему. git status — это карта: «to be committed» подготовлено, «not staged» — правки рабочего дерева, ждущие add, «untracked» — файлы, которых git никогда не видел. Область подготовки существует, чтобы ты мог собрать сфокусированный коммит из подмножества своих изменений, вплоть до отдельных кусков через git add -p. Дальше ты установишь git, задашь свою личность и создашь свой самый первый репозиторий.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 4 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.