Как Git создавать уникальные хэши-коммиты, в основном первые несколько символов?

Мне трудно обернуть голову тем, как Git создает полностью уникальные хэши, которые не могут быть одинаковыми даже в первых четырех символах. Я могу вызвать коммиты в Git Bash, используя только первые четыре символа. В алгоритме конкретно определено, что первые символы являются "ультра" -иническими и никогда не конфликтуют с другими подобными хэшами, или же алгоритм генерирует каждую часть хеша таким же образом?

Ответ 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.