Структура репозитория#
Описание структуры репозитория Git, как с точки зрения физического размещения служебных файлов и каталогов на диске,
так и с точки зрения ключевых логических концепций, определяющих принципы его работы.
Введение: что такое репозиторий Git#
Репозиторий Git — это сердце системы контроля версий. Его можно представить как специальную базу данных, которая
хранит
не только все файлы вашего проекта, но и полную историю их изменений, а также всю служебную информацию, необходимую для
работы. Физически эта «база данных» представляет собой скрытую папку .git в корне вашего проекта.
Существует два основных типа репозиториев:
Локальный репозиторий: Полноценная копия репозитория, расположенная на вашем компьютере. С ней вы работаете напрямую (совершаете коммиты, просматриваете историю, создаёте ветки и т.п.).
Удалённый репозиторий: Версия вашего проекта, размещённая на сервере (например, на
GitLabили внутреннем корпоративном сервере). Используется для обмена изменениями между разработчиками и для резервного копирования кода.
Любая работа начинается с создания или получения локальной копии репозитория.
Логическая структура: состояния файлов#
Прежде чем углубляться в физическое устройство, важно понять логику работы Git. Любой файл в вашем проекте может
находиться в одном из четырех основных состояний (три из которых являются непосредственно отслеживаемыми Git):
Не отслеживаемый (
Untracked) - Файл, который существует в вашей рабочей папке, ноGitникогда о нём не знал ( к примеру только что созданный файл) или вы явно сказалиGitего игнорировать. Может не являться состоянием файла в репозитории, так как он только что создан, либо является игнорируемым файлом.Изменён (
Modified) - Файл был изменён в вашей рабочей папке, ноGitещё не знает, что вы планируете сохранить эти изменения. Другими словами, изменения есть, но они не подготовлены к сохранению, но зафиксированыVCS. Является состоянием уже существующего в репозитории файла.Подготовлен (
Staged): - Вы сообщилиGit, что конкретная версия файла должна войти в следующий «снимок» проекта (Это делается с помощью командыgit add). Файл помещается в специальную промежуточную область, называемую в техническом контекстеИндекс(Staging Area).Зафиксирован (
Committed): - Подготовленные изменения были окончательно сохранены в локальную базу данных репозитория (в локальную папку.git) в виде нового коммита. Файл становится частью истории проекта.
Основные состояния соответствуют трём ключевым физическим секциям проекта Git, которые будут рассмотрены далее:
Рабочий каталог (
Working Tree): Ваши файлы и папки проекта, с которыми вы работаете напрямую.Область подготовленных файлов (
Staging Area / Index): Промежуточная зона, где формируется следующий коммит.Каталог
.git(Git Directory / Repository): База данных, хранящая всю историю и метаданные.
Рабочий процесс работы с состоянием файлов#
Процесс перемещения изменений из рабочего каталога в базу данных репозитория - это перемещение изменений между этими
областями: untracked или modified -> staged -> committed. Он может осуществляться через различные интерфейсы,
два основных из которых - командная строка (Terminal / CLI) и интегрированная среда разработки (IDE).
Работа через командную строку (Terminal / CLI)#
Отслеживание состояний: - Основным инструментом для определения состояния файлов служит команда
git status. Она выводит отчет, разделяющий файлы по их текущим состояниям:
Staged- Перечисляются файлы в секцииChanges to be committed, т.е. подготовленные зафиксированные в локальном репозитории.Modified- Перечисляются файлы в секцииChanges not staged for commit, т.е. файлы изменённые, но не добавленные в фиксацию следующего коммита.Untracked- Перечисляются файлы в секцииUntracked files, т.е. не отслеживаемые файлы, к примеру только что созданные.
Зафиксированные файлы (Состояние
Committed) и файлы, которые игнорируются репозиториемКлючевые операции:
Работа через интегрированную среду разработки (IDE)#
Физическая структура#
При инициализации репозитория в корне вашего проекта создаётся скрытая папка с именем .git. Эта папка и есть
репозиторий Git. Все остальные файлы и папки в вашем проекте (кроме .git) составляют рабочую копию (каталог).
gtk/
├── .git/ # Вся служебная информация Git (сам репозиторий)
│ ├── hooks/* # Директория для клиентских и серверных скриптов-хуков
│ ├── info/* # Глобальные файлы исключений (не отслеживаемые файлы)
│ ├── objects/* # Всё содержимое репозитория (коммиты, файлы, дерево каталогов, аннотированные теги)
│ ├── refs/ # Указатели (ссылки) на коммиты (ветки, теги)
│ │ ├── heads/* # Ссылки на вершины веток (локальные указатели)
│ │ ├── remotes/* # Ссылки на вершины веток (удалённые указатели)
│ │ └── tags/* # Ссылки на теги
│ ├── COMMIT_EDITMSG # Файл, содержащий сообщение последнего выполненного коммита
│ ├── config # Конфигурационный файл именно для этого репозитория (локальная конфигурация)
│ ├── description # Файл с описанием репозитория
│ ├── FETCH_HEAD # Файл, который хранит информацию о последних ветках, загруженных с удаленного сервера
│ ├── HEAD # Файл-указатель на текущую ветку или коммит
│ └── index # Файл, который содержит набор подготовленных файлов для следующего коммита
├── src/* # Ваши файлы проекта (рабочий каталог)
├── build.sbt # Ваши файлы проекта (рабочий каталог)
└── README.md # Ваши файлы проекта (рабочий каталог)
Внимание
Это не полный пример каталога, в нём так же содержатся дополнительные папки и файлы, которые не рассматриваются в данном руководстве.
Рассмотрим ключевые элементы папки .git:
Скрипты-хуки#
Глобальные файлы исключений#
База данных объектов objects/*#
Это самая важная часть репозитория. Git— это, по сути, контентно-адресуемая файловая система, которая содержит
следующие данные:
снимки файлов
blobs,структура каталогов
trees,коммиты
commits,теги
tags,
Они хранятся в виде объектов, каждый из которых идентифицируется своим SHA-1 хешем.
Объекты#
BLOB (
Binary Large Object): Объект, хранящий содержимое одного файла на момент сохранения, то есть снимок относительно предыдущего изменения. Не хранит метаданные.TREE (
Дерево): Объект, представляющий собой один каталог. Он содержит список вложенных в него файлов (указывая наBLOB-объекты) и других каталогов (указывая на другиеTREE-объекты), а также их имена.Commit (
Коммит): Объект, который связывает всё вместе. Он содержит:Указатель на
TREE-объекткорневого каталога проекта на момент коммита.Указатели на родительский(ие) коммит(ы): родительский коммит - это предыдущее состояние, на основе которого сделаны текущие изменения.
Автора (коммитера), дату и время.
Сообщение коммита.
Эта структура формирует направленный ациклический граф, где коммиты связаны друг с другом, что и представляет собой историю проекта.
Система ссылок#
Хранит историю в виде графа коммитов, идентифицируемых только хешами, что неудобно для человека. Для этого существуют
ссылки (refs) - простые файлы, хранящие внутри SHA-1 хеш определённого коммита, но имеющие человеко-читаемые имена.
refs/heads/: Здесь хранятся ссылки на ветки. Имя файла - это имя ветки, а его содержимое - хеш коммита, на который эта ветка в данный момент указывает (её вершина). Например, файлrefs/heads/mainсодержит хеш последнего коммита в веткеmain.refs/tags/: Здесь хранятся ссылки на теги. В отличие от веток, теги - неизменны и всегда указывают на один и тот же коммит, отмечая определённые моменты в истории (например, релизы).
Указатели#
Это специальный файл, который обычно содержит ссылку на текущую активную ветку (т.е. ссылается на файл в refs/heads/).
HEAD указывает на коммит, который в данный момент извлечён в ваш рабочий каталог. Когда вы создаёте новый коммит, он
становится потомком того коммита, на который указывает текущий HEAD, а затем он же (HEAD) перемещается на этот новый
коммит.
Конфигурационные файлы#
config: Файл конфигурации для данного конкретного репозитория. Здесь хранятся настройки, специфичные для этого проекта (например,URLудалённого репозитория, настройки хуков и т.п.)..gitconfig: Глобальный файл конфигурации, применяемый ко всем вашим репозиториям на этом компьютере (например, ваше имя и почта, настройкиcore.editorи т.п.).
Прочие важные элементы#
index: Этот файл (также называемый областью подготовленных файлов) является промежуточной зоной между вашим рабочим каталогом и репозиторием. Когда вы выполняете командуgit add,Gitвычисляет хеш файла и сохраняет эту информацию вindex. При выполненииgit commitсостояниеindexфиксируется в виде новогоtree-объекта, который затем становится частью создаваемого коммита.
Логическая структура#
Любой файл в вашем рабочем каталоге может находиться в одном из трёх основных состояний, определяемых Git:
Modified(Изменён): Файл был изменён в рабочем каталоге, но эти изменения ещё не были отмечены для включения в следующий коммит (не проиндексированы).Git видит изменения, но пока не готов их сохранить в текущий стейдж.Staged(Подготовлен): Изменённый файл был отмечен для включения в следующий коммит с помощью командыgit add. Его текущая версия помещена в область подготовленных файлов - тот самыйindex-файл.Committed(Зафиксирован): Файл безопасно сохранён в вашей локальной базе данных (в папке.git/objects/). Это состояние файла в последнем сделанном коммите.
Эти три состояния соответствуют трём основным секциям проекта Git: рабочему каталогу, области подготовленных файлов (
Индексов) и каталогу .git.