Как вычислить хэш-объект git каталога?
Есть ли у кого-нибудь пример использования хэш-объекта git в каталоге? Он работает достаточно легко в файле *, но не работает так, как я ожидал бы для каталога **
*: git hash-object c:\somefile.txt
**: git hash-object -t tree c:\somedirectory
Когда я пытаюсь использовать хэш-объект с каталогом, он жалуется "фатальный: не может открыть" C:\someDirectory: Permission denied "
Ответы
Ответ 1
git hash-object -t tree
ожидает, что параметр файла будет файлом, который описывает записи в дереве, а не каталог в файловой системе. Я понимаю из комментария здесь, что эта команда ожидает файл, который описывает дерево в двоичном формате, и что было бы проще использовать git mktree
, чтобы создать объект дерева.
git mktree
понимает ввод формата, который вы получаете (например) git ls-tree HEAD
. Хороший пример построения дерева с нуля с помощью git hash-object
и git mktree
в Git Community Book.
Ответ 2
У меня была та же проблема и взломал Python script для хеширования полного каталога. Он ограничен в том смысле, что он не учитывает файл .gitignore
, но он служит своей цели до сих пор (хеш-каталог, сделать объект commit, store это на ветке gh-pages
).
Ответ 3
В зависимости от того, зачем вы это делаете, может понадобиться следующая команда git:
git ls-files -s somedirectory | git hash-object --stdin
Это дает единый хэш, который учитывает имена файлов и их содержимое.
Это работает так. git ls-files -s ....
выводит список файлов и их хэшей в виде текста в stdout
, затем git hash-object
генерирует хеш для данных, которые он получает от stdin
.
Моим вариантом использования является следующее: я хочу знать, соответствуют ли файлы (git) в каталоге в одной ветки точно (*) в другой ветке. Конкретное использование заключается в сравнении "хешей каталогов", решающих, нужно ли повторно генерировать производные файлы, которые кэшируются.
По умолчанию git ls-files
также будет перечислять файлы в подкаталогах. Если вы этого не хотите, попробуйте найти ответы на "как git ls файл только для одного уровня каталога. Существуют также различные другие параметры git ls-files, включая возможность указать список файлов для включения.
(*), исключая хеш-столкновения
Ответ 4
как сказал Марк Лонгэйр, mktree - это путь.
У меня была такая же проблема, и мне пришлось много бороться, чтобы ее исправить. Это то, что я сделал:
git ls-files -s directory_path
Это даст вам список содержимого каталога с его хэшами.
Затем вы можете включить этот список в формат ls-tree в текстовом редакторе и
echo -e "{ls-tree format list}" | git mkdir
Ответ 5
После длительного поиска я нашел следующую команду:
git write-tree
Источник:
http://git-scm.com/docs/git-write-tree
Я использовал его для восстановления отсутствующего каталога:
git write-tree path/to/missing/folder
И мой отсутствующий древовидный объект создан. Отсюда вы можете продолжать использовать:
git hash-object -w path/to/missing/folder/file.txt
Как объясняется в:
https://git.wiki.kernel.org/index.php/GitFaq#How_to_fix_a_broken_repository.3F
Ответ 6
Я хочу улучшить @Fred Foo, предоставив модифицированную версию его script, которая отличается тем, что не хранит файлы и каталоги в репозитории как побочный эффект вычисления их хэшей: http://pastebin.com/BSNGqsqC
К сожалению, я не знаю, как заставить git mktree
не создавать объект дерева в репозитории, поэтому код должен генерировать двоичное представление дерева и передавать его на git hash-object -t tree
.
Этот script основан также на ответах Что такое внутренний формат дерева git?
Общая идея состоит в том, чтобы использовать git hash-object -- data.txt
для получения хэша файла и использовать git hash-object --stdin -t tree < TreeDescription
для каталога, где:
- TreeDescription является конкатенацией
"mode name\0hash"
-
mode
"100644"
для файлов и "40000"
для каталогов (обратите внимание на отсутствие начального нуля в случае каталога)
-
mode
и name
разделяются одним пробелом,
-
name
и hash
разделяются одним байтом \0
-
hash
- это двоичное представление длиной 20 байтов объекта hash
Записи - сортируются по
name
, что кажется не совсем необходимым для создания древовидного объекта, но помогает определить, эквивалентны ли два каталога, сравнивая их хэши - к сожалению, я не знаю, какой алгоритм сортировки следует использовать здесь (в в частности: что делать в случае символов, отличных от ascii)
Также обратите внимание, что этот двоичный формат немного отличается от того, как объект дерева хранится в репозитории, поскольку ему не хватает заголовка "tree SIZE\0"
.
Очевидно, вам нужно вычислить этот снизу вверх, начиная с самых глубоких файлов, так как вам нужно хэши всех детей, прежде чем вычислять хеш родителя.