Техника и логика Git, стоящие за «git status» - PullRequest
3 голосов
/ 01 марта 2012

Что именно происходит, когда git status проверяет наличие изменений в локальной папке?

Насколько я понимаю, каждый файл "зарегистрирован" с помощью хеш-кода (а точнее: sha1), и git status "просто" пытается сопоставить зарегистрированные на сегодняшний день хэши с вычисленными на лету, и если это что-то другое, это считается изменением статуса. Я не очень уверен в этом, если честно, если я ошибаюсь, я бы хотел исправить. В любом случае возникают вопросы:

  1. Где можно найти какие хеши? Есть много хэшей для репо определенных вещей, но где именно я могу найти зарегистрированный хеш для каждого файла?
  2. Что происходит с этими хэшами, если выполняется одна из следующих команд: git add, git commit -am, git gc

Ответы [ 2 ]

5 голосов
/ 02 марта 2012

Чтобы понять это, вам сначала нужно понять объекты git store, все они идентифицируются по их хэшу SHA1. Это коммиты, деревья и капли.

Коммит содержит сообщение о коммите, коммитер, дату, SHA1 родительского коммита (ов) и SHA1 дерева (плюс некоторая дополнительная информация).

Дерево представляет собой каталог. Он содержит имена (и другие метаданные) файлов и каталогов, которые он содержит. Для каждого файла он также содержит SHA1 соответствующего большого двоичного объекта, а для каждого подкаталога он содержит SHA1 другого дерева.

Blob представляет содержимое файла без имени или любых других метаданных.

Теперь git status сравнивает три дерева:

  1. Тот, который принадлежит текущему коммиту (HEAD, обычно последний коммит в текущей ветке).
  2. Тот, что в области подготовки. Это место, куда файлы идут после того, как вы git add их используете, и используется для подготовки коммита до его фактической фиксации.
  3. Ваше рабочее дерево. Вот так выглядит каталог на вашем диске.

Вот почему, если вы редактируете файл (скажем, 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.
2 голосов
/ 01 марта 2012

См. главу 9.2 электронной книги .

Вся электронная книга заслуживает чтения.

...