Проблема в том, что SHA-1 сломан. Не "теоретически устарел", а реально сломан: в 2017 году исследователи показали практическую коллизию. А раз вся модель Git построена на предположении "разный контент - разный хеш", это бьёт в самый фундамент. Поэтому Git мигрирует на SHA-256, и в 2026 году это перестало быть экзотикой для параноиков - это мейнстрим, который вот-вот станет дефолтом. В этом уроке разберём, что именно хранит git хеш, почему shattered git так напугал сообщество, как устроена безопасность git хеш и что конкретно тебе делать на практике.
Что вообще хранит хеш и почему это про целостность, а не шифрование
Сразу убьём частое заблуждение. Хеш в Git - это не шифрование. Ничего не шифруется, ключей нет, расшифровать обратно нельзя в принципе. Хеш - это отпечаток содержимого: берём байты объекта, прогоняем через функцию, получаем строку фиксированной длины. Поменялся хоть один байт - отпечаток меняется полностью.
Давай посмотрим руками, что именно хешируется. Возьмём блоб (содержимое файла):
Код: Выделить всё
$ printf 'hello\n' | git hash-object --stdin
ce013625030ba8dba906f756967f9e9ca394464a
Код: Выделить всё
$ printf 'blob 6\0hello\n' | sha1sum
ce013625030ba8dba906f756967f9e9ca394464a -
Код: Выделить всё
blobКод: Выделить всё
6Зачем всё это? Целостность. Хеш гарантирует, что объект не побился на диске, при передаче по сети, при сбое RAM. Git при каждом обращении может пересчитать хеш и сверить с именем - команда
Код: Выделить всё
git fsck
Почему SHA-1 пришлось менять: shattered git и коллизии
Криптографическая хеш-функция обязана обладать стойкостью к коллизиям: должно быть вычислительно невозможно найти два разных входа с одинаковым хешем. На этом держится всё. Если я могу сделать два разных коммита с одинаковым SHA-1, я могу показать тебе один контент при проверке, а подсунуть другой при клонировании - и Git не заметит подмены, потому что для него это "тот же объект".
В феврале 2017 команда из Google и CWI выкатила атаку SHAttered: они предъявили два разных PDF с одинаковым SHA-1. Это была первая практическая коллизия, и стоила она огромных вычислений, но "дорого" в криптографии означает "сломано" - дальше только дешевле. Отсюда и название: shattered git - это про то, как землю выбили из-под ног у хеша, на котором стоял Git.
Линус Торвальдс тогда справедливо заметил, что архитектура Git смягчает удар: объекты подписаны контекстом, есть распределённость, есть подписи коммитов. Но смягчает - не значит "не проблема". Поэтому сделали две вещи. Короткую и длинную.
Короткая: в Git вшили collision detection. Современный Git использует не голый SHA-1, а sha1dc (sha1collisiondetection) - реализацию, которая на лету ловит признаки именно той математики, что используется в атаках на SHA-1, и аварийно завершается. Эта защита включена по умолчанию. Проверить можно так:
Код: Выделить всё
$ git version --build-options
git version 2.54.0
...
sizeof-size_t: 8
shell-path: /bin/sh
...
Длинная история - это и есть переход на SHA-256, потому что детектор конкретной атаки лечит симптом, а не причину. SHA-1 как фундамент надо менять целиком.
Статус 2026: object-format sha256 становится мейнстримом
Давай по фактам, без мифов, потому что вокруг git sha-256 много путаницы и устаревших статей.
Экспериментальная поддержка SHA-256 появилась ещё в Git 2.29 (2020). С тех пор её довели до боевого состояния. Ключевые вехи к середине 2026:
- Git 2.45 (2024) - заложен фундамент интеропа SHA-1 и SHA-256, чтобы старые репозитории и новые могли сосуществовать.
- Git 2.51 (2025) - SHA-256 объявлен дефолтным форматом, который Git 3.0 будет использовать для новых репозиториев. Тонкий момент: сам по себе 2.51 при всё ещё создаёт SHA-1-репозиторий по умолчанию, но вся внутренняя машинерия уже готова, а курс задан официально.
Код: Выделить всё
git init - Git 2.52 (конец 2025) - стартовала большая работа над живым интеропом SHA-1 и SHA-256. Это сотни патчей, часть сделана, часть в работе.
- Git 3.0 (ожидается к концу 2026) - SHA-256 закрепляется как встроенный дефолт для новых репозиториев. Тогда без флагов начнёт создавать SHA-256-репо.
Код: Выделить всё
git init
Главный сдерживающий фактор - экосистема. На 2026 крупные форджи ещё не все умеют SHA-256. В частности GitHub на момент написания не поддерживает SHA-256-репозитории. Поэтому: для своих внутренних, локальных, security-критичных проектов SHA-256 уже отличный выбор, а вот для зеркалирования на публичный GitHub сперва проверь, что хостинг это принимает.
Практика: как создать и опознать SHA-256-репозиторий
Создаём новый репозиторий на SHA-256 явным флагом:
Код: Выделить всё
$ git init --object-format=sha256 demo256
Initialized empty Git repository in /tmp/demo256/.git/
$ cd demo256
$ git config extensions.objectformat
sha256
Код: Выделить всё
extensions.objectformat=sha256Сделаем коммит и посмотрим на хеш:
Код: Выделить всё
$ printf 'hello\n' > file.txt
$ git add file.txt
$ git -c user.name=dev -c user.email=dev@local commit -m "first"
[main (root-commit) 1b2c3d...] first
$ git rev-parse HEAD
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Код: Выделить всё
ce013625...Код: Выделить всё
$ printf 'hello\n' | git hash-object --stdin
bc02d6d38c44fc0bd1c5f57d36ec06b5e5680a76db3a3a4a76845b96ac9d65b2
Код: Выделить всё
blob 6\0hello\nКод: Выделить всё
$ git config --global init.defaultObjectFormat sha256
Типичные грабли
- Старый Git и чужой инструмент не понимают репо. Если CI, IDE-плагин, ред-тул или хостинг падают с ошибкой "object-format sha256 not supported" - это не баг твоего репозитория, это они ещё не доросли. Прежде чем переводить команду, проверь весь тулчейн, а не только локальный git.
- ] Нельзя смешивать в одном fetch. SHA-1-репозиторий и SHA-256-репозиторий - это два разных мира адресации. Пока интероп не стабилизирован, не жди, что просто добавишь SHA-256-репо как remote к SHA-1 и всё срастётся. Это и есть та работа, что пилится в 2.52+.
- Сокращённые хеши стали длиннее. Привычка копировать "7 символов короткого хеша" работает и тут, но на больших SHA-256-репозиториях Git может показывать больше символов, чтобы избежать неоднозначности. Не удивляйся.
- "Я включу sha256 в конфиге существующего репо". Не сработает и не должно. - это метка того, как репо был создан, а не переключатель. Руками туда лезть нельзя - сломаешь репозиторий.
Код: Выделить всё
extensions.objectformat - Путаница "хеш = защита от злоумышленника". Сам по себе хеш защищает целостность от случайных повреждений и от подмены при условии стойкости функции. От целенаправленной злонамеренной подмену объектов тебя защищают связка стойкого хеша (SHA-256) плюс подписи коммитов и тегов. Одно без другого - полумера.
Сделай по шагам, это 10 минут и снимает всю абстракцию.
- Шаг 1. Создай SHA-1-репо по старинке: , зайди внутрь, сделай коммит с любым файлом.
Код: Выделить всё
git init demo1 - Шаг 2. Посмотри - посчитай символы, их 40.
Код: Выделить всё
git rev-parse HEAD - Шаг 3. Воспроизведи хеш блоба вручную: и сравни с
Код: Выделить всё
printf 'blob 6\0hello\n' | sha1sum. Должны совпасть - ты понял, что хешируется заголовок плюс контент.Код: Выделить всё
printf 'hello\n' | git hash-object --stdin - Шаг 4. Рядом создай SHA-256-репо: . Сделай такой же коммит.
Код: Выделить всё
git init --object-format=sha256 demo256 - Шаг 5. Сравни в обоих. 40 против 64 символов - вот вся разница на глаз.
Код: Выделить всё
git rev-parse HEAD - Шаг 6. Проверь метку: - в первом репо пусто, во втором
Код: Выделить всё
git config extensions.objectformat.Код: Выделить всё
sha256 - Шаг 7. Запусти в обоих - убедись, что целостность проверяется одинаково, независимо от функции хеша.
Код: Выделить всё
git fsck
Контрольные вопросы
- Почему хеш в Git - это про целостность, а не про шифрование? Что конкретно подаётся на вход функции при хешировании блоба?
- Что такое атака SHAttered и почему она опасна именно для модели Git, где имя объекта равно его хешу?
- Чем отличается "SHA-256 - дефолт для будущей Git 3.0" (статус 2.51) от "git init по умолчанию создаёт SHA-256-репо"? На 2026 это одно и то же?
- Можно ли командой git config превратить существующий SHA-1-репозиторий в SHA-256? Почему да или почему нет?
Хеш - это фундамент адресации и целостности в Git, а не шифрование. SHA-1 был скомпрометирован атакой SHAttered в 2017, и Git ответил двумя путями: немедленной защитой через collision detection (включена по умолчанию) и стратегическим переходом на SHA-256. К 2026 SHA-256 - уже не экзотика: с Git 2.51 он назначен дефолтом для грядущей Git 3.0, интероп активно пилится с 2.45 и 2.52, а в самой 3.0 (ожидается к концу 2026) SHA-256 станет дефолтом для новых репозиториев. Создаёшь новый внутренний проект - можешь стартовать на
Код: Выделить всё
git init --object-format=sha256