Ответ 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, другое сообщение фиксации).