Почему git использует хеши вместо номеров ревизий?

80

Мне всегда было интересно, почему git предпочитает хэши, а не номера ревизий. Номера ревизий гораздо понятнее и на них легче ссылаться (на мой взгляд): есть разница между тем, чтобы сказать кому-то взглянуть на ревизию 1200 или зафиксировать 92ba93e! (Просто чтобы привести один пример).

Итак, есть ли причина для этого дизайна?

Макс Бейкирх
источник
3
Вы можете пометить коммит с помощью «v1.0», а затем сослаться на коммит по этому тегу. См. Git-scm.com/book/en/v2/Git-Basics-Tagging
Майкл Даррант

Ответы:

114

Единый монотонно увеличивающийся номер редакции действительно имеет смысл только для централизованной системы контроля версий, где все редакции перенаправляются в одно место, которое может отслеживать и назначать номера. Как только вы попадаете в мир DVCS, где существует множество копий репозитория, а изменения извлекаются и передаются в них в произвольных рабочих процессах, концепция просто не применяется. (Например, нет единого места для назначения номеров ревизий - если я раскошелююсь на ваш репозиторий, а через год вы решите вытащить мои изменения, как система сможет гарантировать, что наши номера ревизий не конфликтуют?)

Джош Келли
источник
11
Возможно, вы захотите взглянуть на путь Bazaar - DVCS, который все еще поддерживает номера ревизий. Единственная гарантия заключается в том, что номера ревизий являются уникальными в пределах одной ветви.
krlmlr
3
@krlmlr Person 1: "Hey, <P2>, what was revision 12345 for?" P2: "Revision 12345 was commited by <P3>." P3: "I don't have a revision 12345..."- Если я правильно помню, у Mercurial есть похожая проблема. С другой стороны, если бы они использовали git, все они имели бы одинаковые ссылки для каждого коммита.
Изката
1
@Izkata: P1: "Do you have revision with the GUID gdlmsnblngoijlafd-35345-fg?"... Базар все еще имеет GUID ...
krlmlr
5
@Izkata Mercurial не имеет аналогичной проблемы. Они используют хеши, как и git. Они также предоставляют местный номер рев для простоты ввода.
Хэнк Гей
1
в git первые 5 символов хэша часто бывают достаточно уникальными, чтобы использовать сокращение для полного идентификатора ревизии.
Мендота
40

Вам нужны хеши в распределенной системе. Допустим, вы и коллега работаете над одним и тем же хранилищем, и вы оба вносите изменения локально, а затем отправляете их. Кто получает номер редакции 1200, а кто номер редакции 1201, если ни одна из сторон не знает друг о друге? Единственное реалистичное техническое решение - создать хэш изменений, используя известный метод, и связать вещи на основе этого.

Интересно, что HG поддерживает номера версий, но они явно предназначены только для локального использования - у вашего репозитория есть один набор, репо вашего коллеги будет иметь другой набор в зависимости от того, как они выдвинулись и вытянулись. Это делает использование командной строки немного более дружественным, чем Git.

Уайетт Барнетт
источник
34

Целостность данных.

Я с уважением не согласен с текущими ответами. Хеши не нужны для DVCS, см. Bazaar . Вы можете сделать то же самое с любым другим глобально уникальным идентификатором. Хэши - это мера, гарантирующая целостность данных: они представляют собой дайджест информации, содержащейся в объекте (коммит, деревья, ...), на который ссылается хеш. Изменение содержимого без изменения хеша (т. Е. Атака с прообразом или атака столкновением ) считается сложной, хотя и не невозможной. (Если вы действительно в этом заинтересованы, посмотрите на статью 2011 года Марка Стивенса ).

Следовательно, обращение к объектам по их хэшу SHA позволяет проверить, не было ли взломано содержимое. И, учитывая, что они (почти) гарантированно являются уникальными, их также можно использовать в качестве идентификаторов ревизий - удобно так.

Смотрите главу 9 книги Git для более подробной информации.

krlmlr
источник
8
Это не мера безопасности, поскольку хэш может быть легко пересчитан для модифицированного коммита. Он используется только для целостности, для проверки содержимого по вычисленному хешу - см. Этот комментарий Линуса Торвальдса об использовании SHA-1 в Git.
Ли
@Lee: Если репозиторий Чака отличается от того, который есть у Алисы и Боба с точки зрения ревизионных хэшей, это гарантирует, что у Чака также есть другое содержимое. С другой стороны, Чаку очень сложно изготовить хранилище с другим содержимым, которое выглядит идентично с их ревизионными хешами.
krlmlr
@Lee: пропустил вашу ссылку. Давайте назовем это «целостность данных» тогда ...
krlmlr
должен быть правильный ответ
SuperUberDuper
8

По словам непрофессионала:

  • Хэши предназначены для почти универсальной уникальности. Это НЕ гарантируется, но крайне маловероятно, что одни и те же SHA создаются для разного контента. В практическом плане для данного проекта вы можете рассматривать его как уникальный.
  • С номерами ревизий вам придется использовать пространство имен, чтобы относиться конкретно к ревизии 1200.
  • Git может работать как распределенный, так и / или централизованный. Так как же получить правильные и уникальные номера ревизий?
  • Кроме того, использование номеров ревизий создаст ложное представление о том, что более новые ревизии должны иметь более высокие номера, и это не будет правдой из-за разветвления, слияния, перебазировки и т. Д.
  • У вас всегда есть возможность поместить теги в коммиты.
Тулаинс Кордова
источник
32
Не гарантированно быть уникальным, просто невероятно вероятно быть уникальным. :)
dsw88
@ mustang2009cobra Это правда.
Тулаинс Кордова
1
Возможно, что мое изменение не будет принято, потому что хэш не изменился. Гораздо более вероятно, что два метеора ударили по моему компьютеру и компьютеру одновременно с хранилищем, уничтожив компьютеры и убив всех участников.
gnasher729
1

Хэш не является уникальным решением для распределенных VCS. Но когда речь идет о распределенной системе, может быть записан только частичный порядок событий. (Для VCS событие может быть фиксацией.) Поэтому поддерживать монотонно увеличивающийся номер ревизии невозможно. Обычно мы принимаем что-то вроде векторных часов (или векторную метку времени) для записи такого частично упорядоченного отношения. Это решение, используемое на базаре .

Но почему Git не использует векторные часы, а использует хэш? Я думаю, что коренной причиной является вишня . Когда мы выполняем cherry-pick в хранилище, частичное упорядочение коммитов меняется. Векторные часы некоторых коммитов должны быть переназначены для представления нового частичного упорядочения. Однако такое переназначение в распределенной системе может вызвать несовместимость векторных тактовых импульсов. Это реальная проблема, с которой сталкиваются хэши.

Че-Шэн Лин
источник