Скільки git sha *, як правило, вважається необхідним для однозначної ідентифікації зміни в заданій кодовій базі?


212

Якщо ви збираєтеся побудувати, скажімо, структуру каталогів, де каталог призначений для фіксації у сховищі Git, і ви хочете, щоб він був досить коротким, щоб очі не кровоточили, але досить довгим, щоб шанс його зіткнувся. було б мізерно мало, скільки взагалі потрібна підрядок SHA?

Скажімо, я хочу однозначно визначити цю зміну: https://github.com/wycats/handlebars.js/commit/e62999f9ece7d9218b9768a908f8df9c11d7e920

Я можу використовувати лише чотири перші символи: https://github.com/wycats/handlebars.js/commit/e629

Але я відчуваю, що це було б ризиковано. Але поширюючи базу даних коду, яка протягом декількох років могла б, скажімо, змінити 30 тис., Які шанси зіткнення, якщо я використаю 8 символів? 12? Чи є число, яке взагалі вважається прийнятним для подібних речей?


Відповіді:


230

На це питання насправді відповідають у 7 главі книги Pro Git :

Як правило, восьми-десяти символів більш ніж достатньо, щоб бути унікальними в рамках проекту. Одним з найбільших проектів Git, ядром Linux, починає потрібно 12 символів із 40 можливих, щоб залишатися унікальними.

7 цифр - це за замовчуванням Git для короткого SHA, тому це добре для більшості проектів. Як уже згадувалося, команда Kernel збільшила їх кількість, оскільки вона має кілька сотень тисяч комісій. Тож для ваших ~ 30 тис. Комісій 8 чи 10 цифр мають бути ідеально чудовими.


38
Також зауважте, що gitце досить розумно. Ви можете встановити абревіатуру короткою, скажімо, на 4, і gitвикористовуватимете 4 цифри для стільки хешів, скільки можливо, але переключитесь на 5 і більше, коли буде відомо, що абревіатура не є унікальною ...
twalberg

31
Зауважте також, що це звичайно стосується лише моменту, коли Git надрукує SHA. Якщо ви "збережіть" скорочені SHA (скажімо, у журналах, електронних листах, чатах тощо) та використаєте їх пізніше для позначення комітетів, вони можуть більше не бути унікальними! Хоча, звичайно, для нормальної довжини, наприклад 7-12 символів, малоймовірно, якщо ви знизитесь до 4 або 5 і отримаєте кілька десяти тисяч нових об'єктів (або зобов’язань, залежно від контексту), це дійсно може повернутися до вас.
Невік Ренель

140

Примітка. Ви можете попросити git rev-parse --shortнайкоротший і в той же час унікальний SHA1.
Див. " Git отримати короткий хеш із звичайного хешу "

git rev-parse --short=4 921103db8259eb9de72f42db8b939895f5651489
92110

Як ви бачите в моєму прикладі, SHA1 має довжину 5, навіть якщо я вказав довжину 4.


Для великих репостів 7 недостатньо з 2010 року, і виконувати dce9648 самим Лінусом Торвальдсом (git 1.7.4.4, жовтень 2010):

За замовчуванням 7 приходить досить рано в розробці git, коли семи шістнадцяткових цифр було багато (він охоплює близько 250+ мільйонів хеш-значень).
Тоді я подумав, що 65k редакцій було багато (це те, що ми збиралися потрапити в BK), і кожна редакція, як правило, становить близько 5-10 нових об'єктів або близько того, тому мільйон об'єктів було великою кількістю.

(BK = BitKeeper)

У наші дні ядро ​​не є навіть найбільшим проектом git, і навіть ядро ​​має близько 220k ревізій ( набагато більше, ніж дерево BK коли-небудь було), і ми наближаємось до двох мільйонів об'єктів.
На даний момент сім шестигранних цифр все ще є унікальними для багатьох з них, але коли ми говоримо лише про два порядки різниці величин між кількістю об'єктів та розміром хешу, відбудуться зіткнення в усічених хеш-значень.
Це вже навіть не близьке до нереального - це відбувається постійно.

Ми повинні збільшити скорочення за замовчуванням, яке було нереально мало, і додати спосіб, щоб люди могли встановити свій власний проект за замовчуванням у файлі git config .

core.abbrev

Встановити імена об’єктів довжини скорочено до.
Якщо не вказано, багато команд скорочують до 7 шестизнак, що може бути недостатньо, щоб скорочені імена об’єктів залишалися унікальними протягом досить тривалого часу.

environment.c:

int minimum_abbrev = 4, default_abbrev = 7;

Примітка. Як зазначається нижче в marco.m , він core.abbrevLengthбув перейменований core.abbrevв той самий Git 1.7.4.4 в команді a71f09f

Перейменувати core.abbrevlengthназад наcore.abbrev

--abbrev=$nЗрештою, це відповідає параметру командного рядка.


Зовсім недавно, Лінус додав зробити e6c587c (для Git 2.11, Q4 2016):
(як зазначено в Матьє Moy «s відповідь )

У досить ранні дні ми якось вирішили скоротити імена об’єктів до 7-шестнадцяткових цифр, але в міру зростання проектів стає все більш імовірним бачити такі короткі назви об'єктів, зроблені в попередні дні і записані в журналі повідомлень, вже не унікальними.

Наразі проект ядра Linux потребує від 11 до 12 гексадигітів, тоді як самому Git потрібно 10 гексадигітів, щоб однозначно ідентифікувати об'єкти, які вони мають, в той час як для багатьох більш дрібних проектів все ще може бути добре з початковим 7-шестнадцатеричним дефіцитом. Однорозмірний підходить не для всіх проектів.

Введіть механізм, де ми оцінюємо кількість об'єктів у сховищі за першим запитом скоротити ім'я об'єкта за замовчуванням та придумати для репозиторію здоровий за замовчуванням. Виходячи з очікування, що ми побачимо зіткнення у сховищі з 2^(2N)об'єктами при використанні імен об'єктів, скорочених до перших N бітів, використовуйте достатню кількість шестизнак, щоб покрити кількість об’єктів у сховищі.
Кожен гексдигіт (4-бітний), який ми додаємо до скороченого імені, дозволяє нам мати чотири рази (2 біти) стільки об'єктів у сховищі.

Див. Комісію e6c587c (01 жовтня 2016 р.) Від Лінуса Торвальда ( torvalds) .
Див. Команду 7b5b772 , вчинення 65acfea (01 жовтня 2016 р.) Хуніо С Хамано ( gitster) .
(Об’єднав Хуніо С Хамано - gitster- в комітеті bb188d0 , 03 жовтня 2016 р.)

Це нове властивість (вгадуючи обґрунтовану за замовчуванням значення абревіатури SHA1) має прямий вплив на те, як Git обчислює власний номер версії для випуску .


3
Ця відповідь дає спосіб перевірити, який найдовший "скорочений" хеш в одному сховищі: stackoverflow.com/a/32406103/1858225
Kyle Strand

1
Зауважте, що core.abbrevLengthбуло перейменовано на core.abbrev.
marco.m

@ marco.m Дякую Відповідь я змінив відповідним чином. І я пов’язаний з комітетом Git, який записує цю нову назву core.abbrev.
VonC

Я просто додам до цього, що ви можете запустити, git rev-parse --short=10 --verify HEADщоб створити 10 символів. Ми МИ використовували git log -1 --format=%h, але це генерувало лише 7 символів, і ми зіткнулися.
grayaii

Дякуємо за пояснення, документи ( git-scm.com/docs/git-rev-parse ) застарілі.
Андре Верланг

36

Це відомо як проблема дня народження.

Для ймовірностей, що не перевищують 1/2, ймовірність зіткнення можна приблизно оцінити як

p ~ = (n 2 ) / (2м)

Де n - кількість предметів, а m - кількість можливостей для кожного предмета.

Кількість можливостей для шістнадцяткових рядків становить 16 c, де c - кількість символів.

Отже, для 8 символів і 30К комітів

30К ~ = 2 15

р ~ = (п 2 ) / (2m) ~ = ((2 15 ) 2 ) / (2 * 16 8 ) = 2 30 /2 33 = ⅛

Збільшивши його до 12 символів

р ~ = (п 2 ) / (2m) ~ = ((2 15 ) 2 ) / (2 * 16 12 ) = 2 30 /2 49 = 2 -19


Саме питання, яке я намагався вирішити, дякую! Таблиця ймовірностей, пов'язана у відповіді @ Messa, також корисна.
Кайл Чадха

чудово, нам більше нічого не потрібно, як це, поясніть це не тільки, що це таке, але й як воно виходить ...
workplaylifecycle

13

На це питання відповіли, але для тих, хто шукає математику позаду - це називається Проблема дня народження ( Wikipedia ).

Йдеться про ймовірність народження 2 (або більше) людей із групи N людей, які мали день народження в один і той же день у році. Що є аналогічним для ймовірності 2 (або більше) git-комітетів із сховища, що має N комітів, що мають однаковий хеш-префікс довжиною X.

Подивіться на таблицю ймовірностей . Наприклад, для хеш-шестигранної рядки довжиною 8 ймовірність зіткнення досягає 1%, коли сховище містить близько 9300 елементів (git commits). Для 110 000 комісій вірогідність становить 75%. Але якщо у вас є хеш-шістнадцятковий рядок довжиною 12, ймовірність зіткнення в 100 000 комітетів нижче 0,1%.


2

Git версія 2.11 (або, можливо, 2.12?) Міститиме функцію, яка адаптує кількість символів, що використовуються у коротких ідентифікаторах (наприклад git log --oneline), під розмір проекту. Щойно ви використовуєте таку версію Git, відповідь на ваше запитання може бути "вибрати будь-яку довжину, яку Git надає вам git log --oneline, це досить безпечно".

Докладніше див. Як змінити типовий параметр "core.abbrev"? дискусія у випуску новин Git Rev 20 і виконувати bb188d00f7 .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.