Вопрос или проблема
Сегодня я изучаю некоторые основы git, читая этот документ онлайн:
http://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-Hi
И в этой главе я начинаю учиться использовать git log --pretty=format:" "
, чтобы показать информацию о логе по своему вкусу.
Но каким-то образом я увидел в таблице форматов два похожих варианта, %H
для Commit Hash
, %P
для Parent Hash
и %T
для Tree Hash
.
Я протестировал их в командной строке, выяснилось, что все они имеют значения хешей одинаковой длины, но разных значений.
Я гуглил и искал на stackoverflow, пока не нашел очевидных подсказок.
У меня есть идея об этом Hash value
, это контрольная сумма этого коммита git.
Но что делают Parent Hash
и Tree hash
?
- PS: Ах, у меня появились некоторые идеи, означал ли
Parent Hash
хеш значением прямого источника ветки?
Хеши родителей:
$ git log --graph
* commit c06c4c912dbd9ee377d14ec8ebe2847cf1a3ec7e
|\ Merge: 79e6924 3113760
| | Author: linjie <[email protected]>
| | Date: Mon Mar 14 16:02:09 2016 +0800
| |
| | commit5
| |
| | Merge branch 'dev'
| |
| * commit 31137606f85d8960fa1640d0881682a081ffa9d0
| | Author: linjie <[email protected]>
| | Date: Mon Mar 14 16:01:26 2016 +0800
| |
| | commit3
| |
* | commit 79e69240ccd218d49d78a72f33002fd6bc62f407
|/ Author: linjie <[email protected]>
| Date: Mon Mar 14 16:01:59 2016 +0800
|
| commit4
|
* commit 7fd4e3fdddb89858d925a89767ec62985ba07f3d
| Author: linjie <[email protected]>
| Date: Mon Mar 14 16:01:00 2016 +0800
|
| commit2
|
* commit 316dd3fb3c7b501bc9974676adcf558a18508dd4
Author: linjie <[email protected]>
Date: Mon Mar 14 16:00:34 2016 +0800
commit1
$ git log --pretty=format:'%<(82)%P %s'
79e69240ccd218d49d78a72f33002fd6bc62f407 31137606f85d8960fa1640d0881682a081ffa9d0 commit5
7fd4e3fdddb89858d925a89767ec62985ba07f3d commit4
7fd4e3fdddb89858d925a89767ec62985ba07f3d commit3
316dd3fb3c7b501bc9974676adcf558a18508dd4 commit2
commit1
Вы можете видеть, что commit4 и commit3 являются родителями commit5, commit2 является родителем commit3 и commit4, commit1 является родителем commit2.
Хэш дерева:
$ git log --pretty=format:'%T %s'
f3c7cee96f33938631a9b023ccf5d8743b00db0e commit5
e0ecb42ae45ddc91c947289f928ea5085c70b208 commit4
d466aea17dc07516c449c58a73b2dc3faa9d11a1 commit3
b39f2e707050e0c5bbb3b48680f416ef05b179ba commit2
5706ec2b32605e27fa04cbef37d582325d14dda9 commit1
$ git cat-file -p f3c7ce
100644 blob 8bb2e871e94c486a867f5cfcbc6f30d004f6a9e5 dev
100644 blob 47f16c8e00adba77ec5c176876e99c8e9f05d69b master
$ git cat-file -p 5706ec
100644 blob fc0bfde0d44bb4d6c7d27b6e587ebedd34ba5911 master
Функция команды: красиво распечатать содержимое <object>
на основе его типа.
git cat-file -p
В git все содержимое хранится как объекты дерева и блоба, где деревья соответствуют записям каталогов в стиле UNIX, а блобы – инодам или содержимому файлов. Один объект дерева содержит одно или несколько записей дерева, каждая из которых содержит указатель SHA-1 на блоб или поддерево с его соответствующим режимом, типом и именем файла. Git обычно создаёт дерево, записывая в него состояние вашей рабочей области или индекса. Объекты коммита содержат информацию о том, кто сохранил объект дерева, когда и почему они его сохранили. Это базовая информация, которую объект коммита хранит для вас.
Заключение:
Commit hash, Parent hash, Tree hash – это все SHA-1. Commit hash и Parent hash идентичны, за исключением того, что Parent hash имеет ребенка. Tree hash представляет объект дерева. Commit hash и Parent hash представляют объект коммита.
Ссылки:
Дерево – это иерархическая коллекция файлов и каталогов, не привязанная к какой-либо конкретной точке в истории. Например, если вы создаете файл, а затем удаляете его (без других промежуточных коммитов), вы получите то же дерево, с которым начинали.
Коммит – это точка в истории вашего проекта. Коммит указывает на дерево, но также содержит другую информацию, такую как автор/коммиттер и время, сообщение о коммите (в котором автор описывает, что изменилось), и, что самое важное, ноль или более родителей, которые являются предыдущим состоянием репозитория. (Ваш первый коммит не имеет родителей. Большинство коммитов после этого имеют одного родителя при линейной разработке и более одного при слиянии.)
Вы можете получить представление о том, как это работает, с помощью команды git cat-file -p
, которая выводит содержимое конкретного хеша независимо от его типа. Например, чтобы просмотреть последний коммит HEAD, вы можете выполнить:
$ git cat-file -p HEAD
tree 81ca1cb660ea79131336944df28b13b711d93557
parent 92b6b8fe9956866ace5397e060e7cc8ee1c76233
parent 7ea2575ed96d150ee19f70edea4bd42c7c2f0b83
author Mislav Marohnić <[email protected]> 1436468108 -0700
committer Mislav Marohnić <[email protected]> 1436468108 -0700
Merge pull request #951 from github/global-args
Избежать зависимости от жестко заданного списка глобальных флагов git
Чтобы увидеть дерево внутри этого коммита, вы можете cat-file -p
его дерево:
$ git cat-file -p 81ca1cb660ea79131336944df28b13b711d93557
100644 blob 730f77a3be502cfe6769c1305c0b59c22274caf5 .gitignore
100644 blob bcbd000f6b9ad5b0510f804ac4a3b19306b39c03 .travis.yml
100644 blob da71aa1fa3c3ae47b2fe5e6245ce2eea1586e278 CONTRIBUTING.md
...
Аналогично, если вы посмотрите на родителей, вы увидите, что это тоже коммиты. Сокращение для дерева внутри коммита, такого как rev
, это rev^{tree}
. Следовательно, предыдущая команда могла быть записана как git cat-file -p HEAD^{tree}
. Обратите внимание, что rev^
обозначает родителя rev
. Когда есть несколько родителей, используют rev^1
, rev^2
и так далее. Больше информации доступно в man-странице git rev-parse.
“Commit Hash” – это хеш для текущего коммита. Коммит, с которым связана запись.
“Parent Hash” – это хеш для любой родительской ветви, из которой происходит коммит.
“Tree hash” – это хеш текущего каталога в коммите. Хеш равен хешу, который имеет каталог, если его посмотреть из родительского каталога с помощью git ls-files --stage --abbrev
.
Справочная информация:
.
Ответ или решение
В Git существует несколько различных типов хешей, которые играют ключевую роль в управлении версиями проекта. Понимание разницы между Commit hash
, Parent hash
и Tree hash
поможет глубже разобраться в работе Git и его архитектуре.
Commit Hash
Commit Hash — это уникальный идентификатор конкретного коммита в репозитории. Обычно это SHA-1 хеш, который представляет собой 40-значное шестнадцатеричное число. Этот хеш генерируется на основе содержимого коммита, таких как дерево, родительские коммиты, автор и сообщение о коммите. Коммит является важной точкой в истории проекта и фиксирует состояние репозитория в определённый момент времени.
Parent Hash
Parent Hash указывает на родительский коммит для текущего коммита. Родительский хеш помогает составить дерево истории измененных версий, позволяя понять, из каких предыдущих состояний произошёл текущий коммит. В случае обычного линейного коммита будет один родитель, однако в случае слияния (merge) у коммита может быть два или более родительских хеша. Это упрощает отслеживание объединений различных веток в проекте и понимание зависимости изменений.
Tree Hash
Tree Hash представляет состояние файловой системы в определённый момент времени, зафиксированной в коммите. Он указывает на объект дерева, который описывает иерархию объектов (файлы и поддиректории) на момент создания коммита. В Git все файлы и каталоги представлены в виде объектов дерева и blob. Blob содержит содержимое файла, а дерево связывает файл с его именем и правами доступа. Таким образом, tree hash описывает структуру проекта на момент коммита, связывая имена файлов с их содержимым (blobs).
Заключение
Понимание схожести и различий между commit hash, parent hash и tree hash позволяет лучше ориентироваться в механизмах работы Git, что существенно облегчает задачу управления кодовой базой при разработке и поддержке проектов. Использование соответствующих команд, таких как git log --pretty=format:" "
, помогает развить навыки в этом направлении, а также улучшает процесс отслеживания истории разработки.
Рекомендации и источники
- Ознакомьтесь с документацией Git для углубленного изучения его внутренних объектов.
- Исследование возможностей команд, таких как
git cat-file -p
, предоставит более детальное представление о структуре объектов внутри вашего репозитория.
В результате применения этих знаний, возможности оптимизации прохода по истории коммитов становятся более очевидными, а анализ изменений — более структурированным и понятным.