Git - Что такое идентификатор фиксации Git?

Как git фиксировать идентификаторы, сгенерированные для однозначной идентификации коммитов?

Пример: 521747298a3790fde1710f3aa2d03b55020575aa

Как это работает? Являются ли они уникальными только для каждого проекта? или для хранилищ git глобально?

Ответ 1

A Git идентификатор фиксации - это SHA-1 хеш о каждой важной вещи о фиксации. Я не буду перечислять их всех, но здесь важные...

  • Содержимое, все это, а не только diff.
  • Дата фиксации.
  • Имя коммиттера и адрес электронной почты.
  • Сообщение журнала.
  • Идентификатор предыдущей фиксации.

Измените это и измените идентификатор фиксации. И да, одна и та же фиксация с теми же свойствами будет иметь тот же идентификатор на другой машине. Это служит трем целям. Во-первых, это означает, что система может определить, была ли изменена фиксация. Он испекла прямо в архитектуру.

Во-вторых, можно быстро сравнивать, просто просматривая их идентификаторы. Это делает сетевые протоколы Git очень эффективными. Хотите сравнить две коммиты, чтобы убедиться, что они одинаковые? Не нужно отправлять весь diff, просто отправьте идентификаторы.

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

origin
A - B - C - D - E [master]

A - B [origin/master]

Сетевой диалог для git fetch origin выглядит примерно так:

  • local Привет, происхождение, какие ветки у вас есть?
  • origin У меня есть мастер в E.
  • local У меня нет E, у меня есть хозяин в B.
  • origin Вы говорите? У меня есть B, и это предок E. Это проверяет. Позвольте мне отправить вам C, D и E.

Вот почему, когда вы переписываете фиксацию с помощью rebase, все после того, как оно должно измениться. Вот пример.

A - B - C - D - E - F - G [master]

Скажем, вы переписываете D, просто немного измените сообщение журнала. Теперь D больше не может быть D, он должен быть скопирован на новую фиксацию, которую мы будем называть D1.

A - B - C - D - E - F - G [master]
         \
          D1

В то время как D1 может иметь C в качестве родителя (C не затронут, коммит не знает своих детей), он отключен от E, F и G. Если мы изменим E родительский на D1, E больше не может быть E. Он должен быть скопирован в новый коммит E1.

A - B - C - D - E - F - G [master]
         \
          D1 - E1

И так далее с F до F1 и G в G1.

A - B - C - D - E - F - G
         \
          D1 - E1 - F1 - G1 [master]

Все они имеют одинаковый код, только разные родители (или в случае D1, другое сообщение фиксации).

Ответ 2

Вы можете точно видеть, что происходит с созданием идентификатора фиксации, запустив

git cat-file commit HEAD

Это даст вам что-то вроде

tree 07e239f2f3d8adc12566eaf66e0ad670f36202b5
parent 543a4849f7201da7bed297b279b7b1e9a086a255
author Justin Howard <[email protected]> 1426631449 -0700
committer Justin Howard <[email protected]> 1426631471 -0700

My commit message

Он дает вам:

  • Контрольная сумма содержимого дерева
  • Идентификатор родительской фиксации (если это слияние, будет больше родителей)
  • Автор фиксации с меткой времени
  • Коммиттер фиксации с меткой времени
  • Сообщение о фиксации

Git берет все это и делает хэш файл sha1. Вы можете воспроизвести идентификатор фиксации, запустив

(printf "commit %s\0" $(git cat-file commit HEAD | wc -c); git cat-file commit HEAD) | sha1sum

Это начинается с печати строки commit, за которой следует пробел и количество байтов . Затем он добавляет blob cat-file к следующему нулевому байту. Все это затем запускается через sha1sum.

Как вы можете видеть, нет ничего, что идентифицировало бы проект или репозиторий в этой информации. Причина, по которой это не вызывает проблем, заключается в том, что астрономически маловероятно, чтобы два разных хеши фиксации столкнулись.