Мне трудно обернуть голову тем, как Git создает полностью уникальные хэши, которые не могут быть одинаковыми даже в первых четырех символах. Я могу вызвать коммиты в Git Bash, используя только первые четыре символа. В алгоритме конкретно определено, что первые символы являются "ультра" -иническими и никогда не конфликтуют с другими подобными хэшами, или же алгоритм генерирует каждую часть хеша таким же образом?
Как Git создавать уникальные хэши-коммиты, в основном первые несколько символов?
Ответ 1
Git использует следующую информацию для генерации sha-1:
- Исходное дерево коммита (которое раскрывает все поддеревья и капли)
- Родительский коммит sha1
- Информация об авторе (с отметкой времени)
- Информация о коммитере (верно, они разные !, также с отметкой времени)
- Сообщение коммита
(полное объяснение; смотрите здесь).
Git НЕ гарантирует, что первые 4 символа будут уникальными. В главе 7 Книги Pro Git написано:
Git может найти короткую уникальную аббревиатуру для ваших значений SHA-1. Если вы передадите --abbrev-commit в команду git log, вывод будет используйте более короткие значения, но оставляйте их уникальными; по умолчанию используется семь символов, но делает их длиннее, если необходимо сохранить SHA-1 однозначный:
Так что Git просто делает аббревиатуру столько, сколько необходимо, чтобы оставаться уникальной. Они даже отмечают, что:
Как правило, от восьми до десяти символов более чем достаточно, чтобы быть уникальным в рамках проекта.
Например, ядро Linux, которое представляет собой довольно большой проект с более 450 тыс. коммитов и 3,6 млн. объектов, не имеет двух объектов, чьи SHA-1 перекрывают больше, чем первые 11 символов.
Так что на самом деле они просто зависят от большой невероятности наличия точно такого же (X первых символов a) ша.
Ответ 2
Апрель 2017 года. Остерегайтесь того, что после всего эпизода shatered.io (где Google столкнулся с SHA1), 20-байтовый формат не будет существовать вечно.
Первым шагом для этого является замена unsigned char sha1[20]
, который является жестким кодом по всей кодовой базе Git, универсальным объектом, определение которого может измениться в будущем (SHA2?, Blake2,...)
См. коммит e86ab2c (21 февраля 2017 г.) от brian m. Карлсон (bk2204
).
Преобразуйте оставшиеся варианты использования
unsigned char [20]
вstruct object_id
.
Это пример текущих усилий, начатых с commit 5f7817c (13 марта 2015 г.) автором brian m. Карлсон (bk2204
), для v2.5.0-rc0, в cache.h
:
/* The length in bytes and in hex digits of an object name (SHA-1 value). */
#define GIT_SHA1_RAWSZ 20
#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
struct object_id {
unsigned char hash[GIT_SHA1_RAWSZ];
};
И не забывайте, что даже с SHA1 4 первых символа уже недостаточно, чтобы гарантировать уникальность, как я объясняю в "Сколько git sha обычно считается необходимым для однозначного определения изменения в заданная кодовая база?".
Обновление в декабре 2017 года с помощью Git 2.16 (первый квартал 2018 года): эта работа по поддержке альтернативного SHA продолжается: см. "Почему Git не использует более современный SHA?".
Вы сможете использовать другой хеш: SHA1 больше не единственный для Git.
Обновление 2018-2019: выбор был сделан в Git 2. 19+: SHA-256.
Смотрите "hash-function-transition".
Это еще не активно (имеется в виду, что git 2.21 все еще использует SHA1), но в настоящее время делается код для поддержки в будущем SHA-256.