Чтобы научится пользоваться git, придётся выяснить как он устроен внутри.

Далее рассматриваются необходимые для понимания внутренние части гита, а также то, как команды git работают с этими внутренностями.

Любой репозиторий содержит директорию .git, выглядит она так:

.git/
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── FETCH_HEAD
├── HEAD
├── hooks
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
├── objects
│   ├── 00
│   ├── 05
│   ├── 06
│   ├── 07
│   ├── 0a
│   ├── f4
│   ├── f5
│   └── f8
├── ORIG_HEAD
├── packed-refs
└── refs
    ├── heads
    ├── remotes
    └── tags

Инициализация

  • git init: создаёт скрытую директорию .git, где хранится вся информация о репозитории.
  • git clone: выкачивает существующий репозиторий, чтобы можно было с ним экспериментировать, он точно также будет содержать .git.

Staging

Внутри .git есть index или, т.н. stage area, там git держит записи о файлах, которые попадут в следующий коммит.

  • git diff —cached: показывает изменения, которые пойдут в следующий коммит.
  • git diff: показывает изменения, которые ещё не стабилизированы (не добавлены в следующий коммит).
  • git status: укороченный результат предыдущих команд.
  • git ls-files —stage: описывает содержимое staging.

Объекты

Внутри .git в директории objects гит хранит все объекты и, фактически, историю изменений и пользовательские файлы, их в терминологии гита называют blob-объектами.

Как читать объекты

  • Сложный способ: использование команд для просмотра содержимого объектов.
    1. Смотрим file .git/objects/ff/7040b0e5c84a00602eb44f9538999193a0e 34b. Видим: zlib compressed data.
    2. apropos -s 1 zlib говорит: zlib-flate (1) - raw zlib compression program. Читаем этот man.
    3. zlib-flate -uncompress < .git/objects/ff/7040* ломает терминал.
    4. Пишем reset, чтобы починить терминал.
    5. zlib-flate -uncompress < .git/objects/ff/7040* | less или | od -c. См od(1), ascii(7).
  • Простой способ: git cat-file -p X для просмотра содержимого объекта X.

А хэш чего?

$ zlib-flate -uncompress < .git/objects/ff/7040* | shasum -
ff7040b0e5c84a00602eb44f9538999193a0e34b  -

Виды объектов

  • Blob: Представляет состояние какого-то файла из репозитория. Хранит его содержимое. Пример: 58311574a8bbc2846b64541ec69889171d54bb0f.
  • Tree: Представляет состояние какой-то директории из репозитория. Хранит список имён в этой директории, а для каждого имени — хэш соответствующего объекта и сведения о Unix-правах на него. Пример: 7c9ffb1cefb4138104612a535fb125c515eb5d95.
  • Commit: Представляет состояние кодовой базы. Хранит хэш корневой директории репозитория, хэши родительских коммитов, имя автора коммита, время коммита и коммит-сообщение. Пример: 3233ffe1c4b99e8efb4c41c6794b4fce880cf503.

git add

Команда git add file1 file2 file3: создаёт blob-объекты и обновляет staging.

git commit

  • По нынешнему index-у строит tree-объект корневой директории;
  • Запоминает хэш “нынешнего” коммита;
  • Считывает коммит-сообщение;
  • Строит коммит-объект, делает его “нынешним” коммитом.