Чтобы понять это, вам сначала нужно понять объекты git store, все они идентифицируются по их хэшу SHA1. Это коммиты, деревья и капли.
Коммит содержит сообщение о коммите, коммитер, дату, SHA1 родительского коммита (ов) и SHA1 дерева (плюс некоторая дополнительная информация).
Дерево представляет собой каталог. Он содержит имена (и другие метаданные) файлов и каталогов, которые он содержит. Для каждого файла он также содержит SHA1 соответствующего большого двоичного объекта, а для каждого подкаталога он содержит SHA1 другого дерева.
Blob представляет содержимое файла без имени или любых других метаданных.
Теперь git status
сравнивает три дерева:
- Тот, который принадлежит текущему коммиту (
HEAD
, обычно последний коммит в текущей ветке).
- Тот, что в области подготовки. Это место, куда файлы идут после того, как вы
git add
их используете, и используется для подготовки коммита до его фактической фиксации.
- Ваше рабочее дерево. Вот так выглядит каталог на вашем диске.
Вот почему, если вы редактируете файл (скажем, a.txt), git add
, редактируете его еще раз, а затем используете git status
, вы получите такой вывод:
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: a.txt
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: a.txt
#
Теперь к вашим актуальным вопросам:
Где можно найти какие хеши? Есть много хэшей для репо определенных вещей, но где именно я могу найти зарегистрированный хеш для каждого файла?
Они хранятся в древовидных объектах. Например, чтобы увидеть объект дерева текущего коммита (HEAD
), используйте git ls-tree HEAD
:
$ git ls-tree HEAD
100644 blob 9c59e24b8393179a5d712de4f990178df5734d99 a.txt
Вы можете видеть, что корневой каталог репо содержит один файл (blob
) с именем a.txt с SHA1 9c59e24b8393179a5d712de4f990178df5734d99.
Вы можете использовать эту же команду для просмотра SHA1 подкаталогов и файлов в этих подкаталогах, подробности см. В документации команды.
Чтобы вычислить SHA1 некоторого файла на диске, вы можете использовать git hash-object
.
Что происходит с этими хэшами, если выполняется одна из следующих команд
Вы должны помнить, что SHA1 основаны на содержимом объекта. И каждый объект полностью неизменен, поэтому SHA1 какого-либо объекта никогда не изменяется. Но многие операции могут создавать новые объекты, и они могут, например, также переходить в какой-либо объект.
git add
берет дерево в области подготовки, модифицирует его, добавляя или изменяя некоторые файлы в соответствии с параметрами команды, и сохраняет измененное дерево обратно в область подготовки.
git commit
берет дерево в области подготовки и создает коммит, который указывает на это дерево. Новый коммит также имеет текущую дату, вы как коммитер и текущий коммит как его родитель. Затем команда изменяет текущую ветвь так, чтобы она указывала на новый коммит.
git commit -a
- это просто сокращение для git add
, за которым следует git commit
.
git gc
просматривает все объекты, которые он хранит, и удаляет те, которые недоступны. Доступные объекты - это подсказки всех ветвей, тегов или текущего коммита, а также всех объектов, на которые они ссылаются, рекурсивно. Недавно использованные коммиты (и объекты, на которые они ссылаются) также не удаляются, потому что они доступны через reflog.