Является ли SHA-1 коммитов рассчитанным только на основе содержимого дерева?

Для эксперимента, скажем, ваш git log идентифицирует следующие коммиты

commit 16bc8486fb34cf9a6faf0f7df606ae72ad9ea438  // added 2nd file
commit 9188f9a25b045f130b08888bc3f638099fa7f212  // initial commit

После фиксации .git/refs/heads/master указывает на 16bc8486fb34cf9a6faf0f7df606ae72ad9ea438.

Скажем, после этого я вручную отредактирую файл .git/refs/heads/master, чтобы указать на 9188f9a25b045f130b08888bc3f638099fa7f212

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

Если я это сделаю.. git log теперь показывает

commit b317f67686f9e6ab1eaabf47073b401d677205d5  // 2nd file committed for the 2nd time
commit 9188f9a25b045f130b08888bc3f638099fa7f212  // initial commit

Вопрос 1:

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

Вопрос 2

На этом этапе произошло то, что произошло с первоначальной второй фиксацией? Когда я делаю git show 16bc8486, он показывает это commit. Однако он не отображается в истории git log.

Ответ 1

Вопрос 1: Поскольку хэш генерируется, принимая во внимание все, включая метаданные фиксации (который сам содержит дату и время).

Вопрос 2: git log показывает журнал текущей ветки. Конец 16bc8486 не является частью этого. Насколько я знаю (я не совсем уверен) сборщик мусора рано или поздно уберет его, если он найдет его, ничего не ссылаясь на него (git gc --help)..

Ответ 2

Значения sha1 для каждого файла blobs будут одинаковыми в обоих случаях, если у вас одинаковый контент (даже если имя файла изменено).

Аналогично, значения sha1 для деревьев для файлов blobs будут одинаковыми, если они имеют одинаковые имена файлов.

Однако на самом верху мы имеем commit, который будет содержать неизменную ссылку на предыдущую фиксацию, верхнее дерево, автора и commiter, но, как сказал KingCrunch, дата автора и commiter будет быть разными, поэтому sha1 команды sha1 будет отличаться.

Вы можете сделать их одинаковыми, если вы намеренно установите дату автора и commiter, используя переменные среды, чтобы они не изменились.

Ответ 3

SHA1 вычисляется из данных diff и всех метаданных из этого фиксации (включая автора и коммиттера, метку времени и различные другие данные).

Для вашего второго вопроса фиксация данных по-прежнему присутствует, но не является частью какой-либо прямой ветки. Иногда git запускает сборку мусора, где удаляются удаленные вещи. Вы заметите, что после того, как вы вручную запустили его с помощью git gc, что незапланированная фиксация исчезнет и даже не будет доступна с помощью git show больше.