Индексирование и фиксация в git
Рассмотрим индексы и коммиты в git
В прошлой статье https://lexusalex.site/posts/git-branches/ мы пришли к пониманию, что такое ветки.
Сегодня подробнее посмотрим подробнее на индексы и коммиты.
Индекс
Если кратко, то индекс в git это промежуточный слой между рабочим каталогом и репозиторием.
В индексе накапливаются изменения о файлах, который потом пойдут в коммит (то есть будут зафиксированны).
Если рассматривать процесс работы над кодом, то он состоит из редактирования файлов в рабочем каталоге, добавление изменений в индекс и фиксация изменений.
То есть из трех составляющих:
1
2
3
Рабочий каталог
Каталог индексирования
Зафиксированная история
При этом добавлять и удалять из индекса до фиксации изменений можно непрерывно.
Если выполнить команду git status
. Она покажет состояние индекса на текущий момент. По сути команда сравнивает рабочий каталог и зафиксированную историю, и выводит различия файлов.
В индекс не попадают содержимое файлов, а выводится только то, что пойдет в следующий коммит.
При выполнении коммита изменения будут взяты из индекса.
Группы файлов в git
git
делит файлы на группы:
- Отслеживаемые -
tracked
- Это файл уже в репозитории или в индексе, его добавляют командойgit add
. - Игнорируемые -
ignored
- Это временные файлы, которые не должны быть в репозитории, для этого используется файл.gitignore
. - Неотслеживаемые -
untracked
- Это файл, который не принадлежит верхним категориям.
Перейдем к примерам:
Вывод, который дает команда git commit
:
Если мы правим уже добавленный файл в репозиторий, он отслеживаемый, и будет добавлен в коммит при добавлении в индекс.
1
2
3
4
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: file
Если мы добавим новый файл, он становиться неотслежиеваемым.
1
2
3
Untracked files:
(use "git add <file>..." to include in what will be committed)
file2
А теперь добавим файл .gitignore
, и включим в него игнорируемый файл file3
, мой редактор будет подсвечивать это так:
.gitignore
иfile2
красные, то есть являются неотслежиеваемыми.file
синий, то есть модифицированный, готовый к коммитуfile3
желтый, игнорируемый, через файл.gitignore
С файлами мы можем делать следующие операции:
- Добавить
- Редактировать
- Удалить
Для каждой из этой операции есть отдельные команды.
git add
git add
добавляет файл в индекс и делает следующее:
- Если файл не отслеживается, он будет добавлен в индекс и ему будет присвоен статус “отслежиеваемый”.
- Если файл был модифицирован, то есть он уже был в репозитории, он будет подсвечен зеленым цветом
modified:file
, то есть готовый к коммиту. - Если файл игнорируемый, то при добавлении его в индекс, получим ошибку
The following paths are ignored by one of your .gitignore files: file3
, что на файл нельзя делать командуgit add
. - Если
git add
применяется к каталогу, все файлы и подкаталоги будут обработаны рекурсивно.
Если не выполнить git add
и модифицировать файл, то получится две версии файла, он был зафиксирован в репозитории, другой в рабочем каталоге.
git rm
git rm
удаляет файл из рабочего каталога и из индекса.
Команда работает только с отслеживаемыми файлами.
У нас есть отслеживаемый неизмененный файл, мы его удаляем и его удаление добавляется в индекс.
1
2
3
4
5
6
7
git rm file
rm 'file'
git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: file
Если файл отслеживаемый и измененный, то удалить и проиндексировать файл можно командой
1
2
3
4
5
6
7
git rm -f file
rm 'file'
git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: file
При любом удалении файла git
будет проверять его версию в последнем коммите и рабочем каталоге, если они различны то не даст удалить, то есть данные не потеряются.
git mv
Для переименования или перемещения файла используется git mv
.
То есть, при выполнении команды, git
это увидит и занесет в индекс
1
2
3
4
5
6
git mv file file8
git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: file -> file8
git
на самом деле не отслеживает переименование, это повлияет только на объекты деревьев.
Коммит
Текущее состояние в определенный момент времени в git называют - коммитом.
Коммит обеспечивает просмотр истории репозитория. Все изменения в репозиторий вносятся строго через коммит.
Обычно коммиты делают разработчики, чтобы зафиксировать часть своей работы, но так бывает не всегда, иногда коммит создается автоматически, либо с помощью программы. Об этом мы поговорим в дальнейших статьях.
Коммиты можно делать часто или редко - это зависит от разработчика. Желательно делать коммит, когда проект находится в стабильном состоянии.
Коммит представляет собой набор изменений по отношению к предыдущему состоянию.
Если в проекте 1000 файлов и все они будут внесены в коммит, это и будет снимком состояния проекта, на текущий момент времени.
Идентификаторы
На коммит можно сослаться явным образом (абсолютным) и неявным способом (относительным).
Явный способ - это уникальный ID коммита, а неявный это символическая ссылка HEAD
, которая указывает на последний коммит в ветке.
Рассмотрим подробнее типы имен коммитов.
Абсолютное имя
Абсолютное имя, это SHA-1
хеш объекта коммита.
Например: 98e1addacbfee2d477e1a881409d1f48b751bcc1
.
Его особенности:
- Хеш относится только к конкретному коммиту.
- Неважно где в истории будет находиться коммит.
- ID коммит уникален в рамках всего репозитория.
- 40 символов можно сократить, до уникального префикса внутри репозитория, например
98e1adda
.
Эта ссылка четко
указывает на объект коммита в дереве объектов git.
Относительное имя
Так же могут быть символические ссылки, которые указывают на коммит косвенно.
Каждая символическая ссылка имеет полное имя, которое начинается с refs
в каталоге .git
.
refs/heads
- локальные веткиrefs/remotes
- удаленные ветки отслеживанияrefs/tags
- теги
Например, имя локальной представлено как refs/heads/main
, а удаленной ветки отслеживания refs/remotes/origin/main
, а тег как refs/tags/v0.1.1
.
При поиске ссылки можно использовать полноценное имя или ее псевдоним.
Внутри git
использует при поиске правило первого совпадения согласно перечню:
.git
.git/refs
.git/refs/tags
.git/refs/heads
.git/refs/remotes
.git/refs/remotes/../HEAD
.
В git
по умолчанию есть следующие символические ссылки:
HEAD
- последний коммит в ветке. При переключении ветокHEAD
обновляется и указывает на последний коммит переключенной ветки.ORIG_HEAD
- предыдущая версияHEAD
, используется для отката к предыдущему состоянию слиянию и сбросу.FETCH_HEAD
- используется для удаленных репозиториев, куда пишутся ID извлекаемых ветокMERGE_HEAD
- Используется при слиянии веток.
Мы можем ссылаться относительно последнего коммита в ветке, по истории вверх, например:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
git show-branch --more=100
! [branch-1] commit 6
! [branch-2] commit 3
! [branch-3] commit 7
* [branch-4] commit 8
! [main] commit 1
-----
* [branch-4] commit 8
+* [branch-3] commit 7
+* [branch-3^] commit 4
++* [branch-2] commit 3
+ [branch-1] commit 6
+ [branch-1^] commit 5
+++* [branch-2^] commit 2
+++*+ [main] commit 1
История коммитов
Одна из важных вещей - это просмотр истории. Для этого используется команда git log
.
Если просто выполнить команду, то будут выведены коммиты в обратном хронологическом порядке, от последнего коммита
1
2
3
4
5
6
7
git log
commit 5adb352052433ef484e5979be8800dd004e3ce44 (HEAD -> branch-4)
Author: <>
Date: Sun Dec 15 17:45:04 2024 +0300
commit 8
...
Чтобы более детально вывести информацию, нужно задать точку откуда смотреть историю
1
git log branch-3
Также можно сократить кол-во выводимых коммитов, например выведем 1 коммит
1
git log branch-3 -1
Более подробно команду git log
рассмотрим отдельно.
Хотите оптимизировать свой бизнес, нужен сервис, сайт или интеграция.
Бесплатно расчитаю время разработки, предложу решение вашей задачи.