Правильный ответ на вопрос в теме письма:
Объекты Git SHA-1 - это содержимое файла или имена файлов?
вероятно, «ни то, ни другое», поскольку вы имели в виду содержимое свободного объектного файла, а не исходный файл, и даже если вы имели в виду исходный файл, это все равно не совсем правильно.
Свободный объект в Git — это обычный файл. Имя файла создается из хэш-идентификатора объекта. Идентификатор хеша объекта, в свою очередь, создается путем вычисления хэша содержимого объекта с прикрепленным заголовком-префиксом.
Заголовок с префиксом зависит от типа объекта. Существует четыре типа: blob
, commit
, tag
и tree
. Заголовок состоит из завершающейся нулем строки байтов, состоящей из имени типа в виде строки байтов ASCII (или, что эквивалентно, UTF-8), за которым следует пробел, за которым следует десятичное представление размера объекта в байтах, за которым следует с помощью ASCII NUL (b'\x00'
в Python, если вы предпочитаете современную нотацию Python, или '\0'
, если вы предпочитаете C).
После заголовка идет фактическое содержимое объекта. Таким образом, для файла, содержащего строку байтов b'hello\n'
, хэшируемые данные состоят из b'blob 6\0hello\n
:
$ echo 'hello' | git hash-object -t blob --stdin
ce013625030ba8dba906f756967f9e9ca394464a
$ python3
[...]
>>> import hashlib
>>> s = b'blob 6\0hello\n'
>>> hashlib.sha1(s).hexdigest()
'ce013625030ba8dba906f756967f9e9ca394464a'
Следовательно, имя файла, которое будет использоваться для хранения этого файла, будет (производным) ce013625030ba8dba906f756967f9e9ca394464a
. Как свободный объект, он становится .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
.
Однако содержимое этого файла представляет собой сжатую zlib форму b'blob 6\0hello\n'
(с, по-видимому, level=1
— по умолчанию в настоящее время 6, и результат не совпадает на этом уровне; неясно, является ли Git zlib deflate точно соответствует Python, но здесь сработал уровень 1):
$ echo 'hello' | git hash-object -w -t blob --stdin
ce013625030ba8dba906f756967f9e9ca394464a
$ vis .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
x\^AK\M-J\M-IOR0c\M-HH\M-M\M-I\M-I\M-g\^B\000\^]\M-E\^D\^T$
(обратите внимание, что последний $
снова является приглашением оболочки; теперь вернемся к Python3)
>>> import zlib
>>> zlib.compress(s, 1)
b'x\x01K\xca\xc9OR0c\xc8H\xcd\xc9\xc9\xe7\x02\x00\x1d\xc5\x04\x14'
>>> import vis
>>> print(vis.vis(zlib.compress(s, 1)))
x\^AK\M-J\M-IOR0c\M-HH\M-M\M-I\M-I\M-g\^B\^@\^]\M-E\^D\^T
где vis.py
это:
def vischr(byte):
"encode characters the way vis(1) does by default"
if byte in b' \t\n':
return chr(byte)
# control chars: \^X; del: \^?
if byte < 32 or byte == 127:
return r'\^' + chr(byte ^ 64)
# printable characters, 32..126
if byte < 128:
return chr(byte)
# meta characters: prefix with \M^ or \M-
byte -= 128
if byte < 32 or byte == 127:
return r'\M^' + chr(byte ^ 64)
return r'\M-' + chr(byte)
def vis(bytestr):
"same as vis(1)"
return ''.join(vischr(c) for c in bytestr)
(vis
производит обратимую, но печатаемую кодировку двоичных файлов; это был мой ответ 1993 года на проблемы с cat -v
).
Обратите внимание, что имена файлов, хранящиеся в репозитории Git (при фиксации), отображаются только как компоненты пути, хранящиеся в отдельных tree
объектах. Вычисление хэш-идентификатора объекта дерева нетривиально; У меня есть код Python, который делает это в моем общедоступном репозитории «скриптов» в разделе githash.py< /а>.
person
torek
schedule
10.06.2017
git cat-file -p [sha1]
и вы лучше поймете... - person Philippe   schedule 10.06.2017