вычислить хэш рабочего дерева 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>
уникален.