Перейти к содержанию

Индекс

Индекс в Git это специальная промежуточная область, в которой хранятся изменения файлов на пути от рабочей директории до репозитория. При выполнении коммита в него попадают только те изменения, которые были добавлены в индекс. В этом уроке мы разберем способы наполнять индекс: от коротких сокращений до выбора отдельных строк.

Индекс нужен потому, что правки в рабочей директории редко относятся к одной задаче. Разработчик делает основное изменение, а по пути исправляет ошибку, переоформляет соседний фрагмент, правит устаревший комментарий. Если сложить это в один коммит, получится запись, которую потом не прочитать и не откатить по частям:

# Обычно в таких коммитах встречается условие И в описании
# Это показатель того, что в рамках одного коммита сделано несколько изменений
git commit -m 'add new feature and fix something'

Индекс дает выбор: что из сделанного уйдет в этот коммит, а что подождет следующего.

Сокращения

Стандартный способ работы с индексом это добавление или изменение файлов и последующий коммит:

git add somefile
git commit -m 'add somefile'

Если речь идет про один-два файла, которые нужно закоммитить прямо сейчас, то можно сделать проще. Этот подход работает только с уже отслеживаемыми файлами:

echo 'new data' >> INFO.md
# Не нужно явно вызывать команду `git add`
git commit INFO.md -m 'update INFO.md'

Есть и обратная ситуация: мы исправили много файлов и хотим отправить в коммит сразу все. Для этого есть три сокращения:

# Добавляет в индекс все изменения текущего каталога и его подкаталогов
git add .

# Добавляет в индекс изменения всего репозитория, независимо от текущего каталога
git add -A

# Флаг -a добавляет в индекс изменения и удаления и сразу коммитит
# Новые файлы он не добавляет, их по-прежнему нужно передать в `git add`
git commit -am 'do something'

Точка это текущий каталог, а не корень репозитория. Если вызвать git add . из подкаталога, изменения за его пределами в индекс не попадут.

Все три команды очень опасны. С их помощью крайне легко закоммитить много лишнего, особенно если перед коммитом не посмотреть git diff --staged. Они экономят секунды, а разбор случайно попавшего в историю файла занимает часы.

Выбор отдельных изменений

Бывает и так, что разные по смыслу правки сделаны в одном файле. Целиком его в коммит отдавать нельзя, а разделять руками долго. Здесь помогает команда git add -p: она показывает измененные куски по одному и спрашивает, брать ли их в индекс.

git add -p INFO.md

diff --git a/INFO.md b/INFO.md
index 40f51f1..b0e7c1e 100644
--- a/INFO.md
+++ b/INFO.md
@@ -1,2 +1,3 @@
 git is awesome!
 new line
+fix typo in docs
(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? y

Отвечать нужно одной буквой. Ответ y кладет кусок в индекс, n пропускает его и оставляет только в рабочей директории, q завершает разбор. Полный список Git печатает по ?.

Правки, которые стоят в файле рядом, Git показывает одним куском. Допустим, в INFO.md из трех строк, которые уже лежат в коммите, мы исправили регистр в первой строке и дописали строку в конец. Ответ s делит такой кусок на части по неизмененным строкам между правками, и дальше Git спрашивает про каждую часть отдельно.

$ git add -p INFO.md
diff --git a/INFO.md b/INFO.md
index 7e0c837..e333486 100644
--- a/INFO.md
+++ b/INFO.md
@@ -1,3 +1,4 @@
-git is awesome!
+Git is awesome!
 new line
 fix typo in docs
+index keeps the next commit
(1/1) Stage this hunk [y,n,q,a,d,s,e,p,P,?]? s
Split into 2 hunks.
@@ -1,3 +1,3 @@
-git is awesome!
+Git is awesome!
 new line
 fix typo in docs
(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? y
@@ -2,2 +2,3 @@
 new line
 fix typo in docs
+index keeps the next commit
(2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]? n

В этом примере в индекс ушло исправление первой строки, а новая строка осталась в рабочей директории. Если между правками нет ни одной неизмененной строки, s кусок не разделит, и Git не предложит этот ответ.

Тот же режим доступен через интерактивное меню git add -i, где нужно выбрать пункт patch. Ниже запись сессии, в которой один файл с двумя несвязанными правками расходится по двум коммитам:

Демонстрация

В записи имя ветки другое, в вашем репозитории на ее месте будет main.

С помощью этой команды можно очень точно выбрать то, что должно попасть в коммит, а что нет. Ее использование обычно показывает хороший уровень владения Git.

Дополнительные материалы

  1. Интерактивное индексирование

Самостоятельная работа

Попрактикуйтесь в использовании команд из урока, меняя содержимое репозитория.