вычислить хэш рабочего дерева git

Я использовал «git rev-parse HEAD:» для вычисления хэша папки в рабочем дереве. это в основном то же поведение, что и «git ls-tree:».

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

Теперь я хочу изменить свою логику, чтобы включить эти изменения, чтобы вычислить хэш папки, но из текущего состояния рабочего дерева, а не фиксации. предпочтительно использовать ту же логику, что и ls-tree (поскольку мы использовали этот код до сих пор и хотим поддерживать совместимость).

Как это может быть сделано? буду очень признателен за любую помощь

1 ответ

Вы начинаете с неправильного представления: Git не хранит папки и, следовательно, не хэширует папки. Хотя, возможно, вы все еще можете делать то, что хотите.

Гит-магазины:

  • содержимое файла (как «объекты больших двоичных объектов»): хэш-идентификатор объекта большого двоичного объекта представляет собой контрольную сумму слова blob, пробел, десятичный размер файла в байтах, нулевой байт и байты файла (в таком порядке, когда все рассматривается как один 8-битный байт, т. е. в Python вы использовали бы f"blob {len(data)}\0".encode() + dataв качестве входных данных для хэшера);

  • древовидные объекты (в которых хранятся имена, режимы и хеш-кортежи): именно так имена файлов и хэши больших двоичных объектов сохраняются в коммитах, хотя здесь есть сложности: порядок сортировки в конкретных случаях имеет значение, а имена разбиваются на компоненты;

  • зафиксировать объекты; а также

  • аннотированные объекты тегов.

Как и в случае объектов blob, объекты дерева, фиксации и аннотированного тега имеют заголовки в начале, состоящие из типа, пробела, размера (десятичное числовое представление ASCII) и байта NUL. Типовые строки для этих трех tree, commit, а также tagсоответственно.

Как вы заметили, результат git rev-parse HEAD:является хэш-идентификатором объекта дерева, хранящегося в HEADсовершить. Вы можете построить древовидный объект из всего, что находится в индексе Git, используя , хотя индекс должен содержать все нужные BLOB-объекты файлов и имена путей и в настоящее время не должен содержать никаких конфликтов слияния.

Чтобы вычислить, каким будет хеш-идентификатор для некоторого дерева, создайте пустой индекс, 1 добавьте это дерево к этому пустому индексу и используйте для создания объекта дерева из этого индекса. Этот объект дерева будет храниться в репозитории. Если вы никогда не будете использовать его ни для чего, это немного расточительно, но сборщик мусора Git в конечном итоге соберет его, если вы работаете с системой в обычном режиме. Из-за проблем с упорядочением и компоновкой компонентов при построении объектов дерева это единственный способ сделать это непосредственно в Git.

В сценарии оболочки вы можете использовать следующее (обратите внимание, что это полностью не проверено):

      export GIT_INDEX_FILE=/tmp/index.test.$$
rm -f $GIT_INDEX_FILE
trap "rm -f $GIT_INDEX_FILE" 0 1 2 3 15
git add .
git write-tree

Стандартный вывод из этой последовательности команд представляет собой хэш-идентификатор дерева (распечатанный git write-tree).

Если вы хотите сделать это на языке программирования, посмотрите мой код Python , который это делает, но обратите внимание на все ограничения.


1Git на самом деле не допускает пустого индекса, но считает несуществующий файл индекса существующим, но пустым. Следовательно rm -fкак строку для «создания» «пустого индекса». Было бы неплохо поместить файл индекса в git rev-parse --git-dirскорее, чем /tmpи/или использовать mktempа не просто предположить, что index.test.<pid>уникален.

Другие вопросы по тегам