Является ли git полусекретным пустым древовидным объектом надежным, и почему нет символического имени для него?

Git имеет хорошо известное или, по крайней мере, хорошо известное пустое дерево, SHA1 которого:

4b825dc642cb6eb9a060e54bf8d69288fbee4904

(вы можете увидеть это в любом репо, даже недавно созданном, с git cat-file -t и git cat-file -p).

Если вы много работаете и очень осторожны, вы можете использовать это пустое дерево для хранения каталога, у которого нет файлов (см. answer to Как добавить пустой каталог в git), хотя это не очень хорошая идея.

Это более полезно как один аргумент для git diff-tree, который делает один из примеров hooks.

Мне интересно,

  • Насколько надежна эта i.e, будет ли в будущей версии git объект git пронумерован 4b825dc642cb6eb9a060e54bf8d69288fbee4904?
  • Почему нет символьного имени для пустого дерева (или есть один?).

(Быстрый и грязный способ создания символического имени состоит в том, чтобы поместить SHA1 в, например, .git/Nulltree. К сожалению, вы должны сделать это для каждого репо. Лучше просто поместить магическое число в скрипты и т.д. У меня просто общее отвращение к магическим числам.)

Ответ 1

Этот поток упоминает:

Если вы не помните пустое дерево sha1, вы всегда можете получить его с помощью:

  git hash-object -t tree/dev/null
Код>

Или, как Ciro Santilli предлагает в комментариях:

  printf '' | Git hash-object --stdin -t tree
Код>

Итак, я полагаю, что безопаснее определять переменную с результатом этой команды в качестве вашего пустого дерева sha1 (вместо того, чтобы полагаться на "известное значение" ).


Обратите внимание: вы увидите, что SHA1 появляется на каком-то репозитории GitHub, когда автор хочет, чтобы его первая фиксация была пустой (см. сообщение в блоге " Как я инициализирую свои репозитории Git):

  $GIT_AUTHOR_DATE = "Thu, 01 Jan 1970 00:00:00 +0000" GIT_COMMITTER_DATE = "Чт, 01 янв 1970 00:00:00 +0000" Git commit --allow-empty -m 'Первоначальная фиксация'
Код>

Вы получите:

Пустое дерево SHA1

(см. дерево SHA1?)

Вы даже можете пересоздать существующую историю поверх этой пустой фиксации (см. " git: как вставить фиксацию в качестве первой, смещение всех остальных?" )

В обоих случаях вы не полагаетесь на точное значение SHA1 этого пустого дерева.
Вы просто следуете рекомендациям , инициализируя свое репо с помощью первого пустого коммита.


Для этого:

  git init my_new_repo
cd my_new_repo
git config user.name имя пользователя
git config user.email email @com

git commit --allow-empty -m "initial empty commit" 
Код>

Это приведет к фиксации с SHA1, специфичным для вашего репо, имени пользователя, электронной почты, дате создания (что означает, что SHA1 самой фиксации будет отличаться каждый раз). Но дерево, на которое ссылается эта фиксация, будет 4b825dc642cb6eb9a060e54bf8d69288fbee4904, пустым деревом SHA1.

  git log --pretty = raw

совершить 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14
Дерево 4b825dc642cb6eb9a060e54bf8d69288fbee4904 < ====
автор VonC < [email protected]> 1381232247 +0200
committer VonC < [email protected]> 1381232247 +0200
   начальная пустая фиксация
Код>

Чтобы показать только дерево фиксации (отобразить дерево фиксации SHA1):

  git show --pretty = format:% T 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14
4b825dc642cb6eb9a060e54bf8d69288fbee4904
Код>

Если это commit, ссылаясь на пустое дерево, действительно является вашим первым commit, вы можете показать это пустое дерево SHA1 с помощью:

  git log --pretty = формат:% h - обратный | head -1 | xargs Git show --pretty = format:% T
4b825dc642cb6eb9a060e54bf8d69288fbee4904
Код>

(и это даже работает в Windows, команды Gnu On Windows)


Как ниже,, используя git diff <commit> HEAD, это покажет весь ваш файл в текущей ветке HEAD:

  git diff - только имя-4b825dc642cb6eb9a060e54bf8d69288fbee4904 HEAD
Код>

Примечание: это пустое значение дерева формально определено в <код > cache.hкод > .

  #define EMPTY_TREE_SHA1_HEX \    "4b825dc642cb6eb9a060e54bf8d69288fbee4904" 
Код>

Теперь (Git 2.16, Q1 2018) используется в структуре, которая больше не привязана к (только) SHA1, как видно из commit eb0ccfd:

Переключить поиск пустых деревьев и блоков, чтобы использовать хеш-абстракцию

Переключите использование empty_tree_oid и empty_blob_oid, чтобы использовать абстракцию current_hash, которая представляет текущий хеш-алгоритм в использовать.

Подробнее в разделе Почему Git не использует более современные SHA? "

Ответ 2

Я написал сообщение в блоге с двумя разными способами поиска хеша: http://colinschimmelfing.com/blog/gits-empty-tree/

Если бы он почему-то изменился по какой-то причине, вы могли бы использовать два пути ниже, чтобы найти его. Тем не менее, , я бы довольно уверенно использовал хэш в псевдонимах .bashrc и т.д., И я не думаю, что он изменится в ближайшее время. По крайней мере, это, вероятно, будет основной выпуск git.

Два способа:

  • Ответ выше: git hash-object -t tree --stdin < /dev/null
  • Просто инициализируя пустое репо, а затем запустив git write-tree в этом новом репо - хеш будет выводиться с помощью git дерева записи.