Вы когда-нибудь задумывались, как Git так быстро работает? Как он хранит всю историю проекта, но при этом занимает так мало места? Давайте заглянем под капот!
Магия Git: снимки, а не изменения
Большинство систем контроля версий хранят изменения (дельты):
Файл v1: "Hello"
Изменение 1: +5 символов " World"
Изменение 2: +1 символ "!"
Git работает по-другому. Он делает снимки (snapshots) всего проекта:
Коммит 1: полный снимок проекта
Коммит 2: полный снимок проекта (с изменениями)
Коммит 3: полный снимок проекта
Как это работает?
1. Хеширование (SHA-1)
Каждый файл Git превращает в уникальный хеш (контрольную сумму):
# Файл: hello.txt содержит "Hello World"
# Git вычисляет SHA-1 хеш:
557db03de997c86a4a028e1ebd3a1ceb225be238
Если файл не изменился — хеш тот же самый!
Если хоть один символ изменился — совершенно новый хеш.
2. Объекты Git
Git хранит 4 типа объектов:
1. Blob (Binary Large Object)
- Содержимое файла
- Просто данные, без имени файла
2. Tree (Дерево)
- Папка в файловой системе
- Список файлов (blob) и подпапок (tree)
3. Commit (Коммит)
- Снимок проекта в момент времени
- Ссылается на tree
- Ссылается на родительский commit
- Содержит автора, дату, сообщение
4. Tag (Метка)
- Именованная метка коммита
- Например, “v1.0.0”
Пример: как Git хранит коммит
Представим простой проект:
my-project/
├── README.md
└── src/
└── main.py
Что создаёт Git:
BLOB для README.md
hash: abc123...
content: "# My Project\n..."
BLOB для main.py
hash: def456...
content: "print('Hello')"
TREE для src/
hash: ghi789...
main.py -> def456...
TREE для корня
hash: jkl012...
README.md -> abc123...
src -> ghi789...
COMMIT
hash: mno345...
tree: jkl012...
parent: предыдущий коммит
author: "Вася <vasya@example.com>"
date: "2026-04-10 15:00:00"
message: "Добавил README"
Экономия места: дедупликация
Умная фишка: если файл не изменился между коммитами, Git НЕ создаёт новую копию!
Коммит 1:
README.md -> blob abc123
Коммит 2 (изменил только main.py):
README.md -> blob abc123 (ТОТ ЖЕ blob!)
main.py -> blob xyz999 (новый blob)
Результат: огромная экономия места!
Сжатие и pack файлы
Со временем Git дополнительно сжимает объекты в pack files:
- Похожие файлы компрессируются вместе
- Старые версии файлов хранятся как дельты (изменения)
- Это происходит автоматически
Преимущества подхода Git
✅ Скорость
Все операции локальные:
- Просмотр истории — мгновенно
- Переключение веток — секунды
- Сравнение версий — быстро
✅ Целостность
Каждый объект идентифицируется по хешу:
- Невозможно изменить прошлое незаметно
- Любая коррупция данных будет обнаружена
- История защищена криптографически
✅ Компактность
Благодаря дедупликации и сжатию:
- Множество версий файлов занимают мало места
- Можно хранить полную историю проекта
✅ Распределённость
Каждый клон — полная копия:
- Вся история проекта
- Все ветки
- Все теги
Где Git хранит данные?
Всё находится в папке .git/:
.git/
├── objects/ # Blob, tree, commit объекты
├── refs/ # Ссылки на ветки и теги
├── HEAD # Текущая ветка
├── index # Staging area
└── config # Конфигурация
Практический пример
# Создаём файл
echo "Hello Git" > test.txt
# Добавляем в staging
git add test.txt
# Git создал blob объект!
# Можно посмотреть его содержимое:
git cat-file -p abc123...
# Делаем коммит
git commit -m "Add test"
# Git создал:
# - blob для test.txt
# - tree для корня
# - commit объект
Интересные факты
🔍 SHA-1 коллизии:
- Теоретически возможны
- На практике вероятность ничтожна
- Git переходит на SHA-256
📦 Размер .git папки:
- Обычно 10-30% от размера проекта
- У Linux kernel: ~3GB кода, ~1.5GB .git
- 20+ лет истории в 1.5GB!
🚀 Скорость:
- git log — мгновенно (локальная БД)
- svn log — секунды (запрос к серверу)
Выводы
Git умный потому что:
- ✅ Хранит снимки, а не дельты
- ✅ Использует хеширование для идентификации
- ✅ Дедуплицирует неизменённые файлы
- ✅ Сжимает данные автоматически
- ✅ Работает локально (быстро!)
Теперь вы понимаете почему Git такой быстрый и эффективный! 🚀
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!