Какие сантехнические команды достигают того же уровня, что и git add?
Я хотел бы лучше понять git-сантехнику, узнав, что на самом деле происходит при входе
git add $DIRECTORY
а также
git add $FILE
Как это работает?
Грубая идея может быть получена, прочитав секцию git inners progit.
- Если
$DIRECTORY
это каталог, что-то вродеfind $DIRECTORY -type f -exec git add {} \;
т.е. рекурсивное добавление всех файлов в$DIRECTORY
, Затем,git add $FILENAME
применяется для каждого файла. - Проверка против
.gitignore
(и его "начальство") - Проверка против
.gitattributes
работаетclean
фильтр, если применимо git hash-object -w
clean
содержание
И затем, индекс получает обновления как-то, что включает в себя git mktree. Но что именно там происходит? Содержит ли дерево для каталога только добавленные файлы или все файлы, которые были ранее зафиксированы? А что будет дальше?
1 ответ
git add
не имеет ни одной эквивалентной команды сантехника, но, вероятно, самая близкая git update-index
, Описание ProGit верно:
Замените каждый каталог списком содержимого каталога. Результатом является список файлов, указанных
add
с некоторой особой обработкой случаев для файлов, о которых сейчас известно, что они не находятся в каталоге (то есть удалены), и для файлов со специальными индексными состояниями (--assume-unchanged
а также--skip-worktree
). Другими словами, этот шаг также обращается к текущему индексу.Проверить на неподключенную, но игнорируемую (через
.gitignore
) файлы и исключить их из списка (с предупреждением), если не указано иное-f
/--force
,(Примечание: я не проверял это в подкаталогах, и возможно, что
-f
не будет применяться к записи подкаталога, выбранной при рекурсивном сканировании, но только к именам, фактически указанным в командной строке. В этом случае шаг 2 должен быть объединен с шагом 1, чтобы имена не добавлялись, если мы собираемся игнорировать их даже при-f
.)Примените атрибуты, если они есть, создавая временно очищенные копии файлов, если это необходимо.
использование
git update-index --add --remove --replace
чтобы получить измененные файлы, записанные в хранилище, с обновленными записями их индексов, включая обновления режима. (Для файлов, очищенных на шаге 3, вам придется использовать отдельныйgit hash-object -w
, как вы предложили, и--index-info
вместо--add --remove --replace
.)
git mktree
команда вообще не входит в этот процесс, так как сам индекс представляет собой просто плоский файл, использующий плохо документированный формат (или, точнее, один из нескольких форматов; см. --index-version
).
Индекс допускает до четырех записей для каждого имени файла, которые называются этапами: этап 0 является обычной записью в кэш, а этапы с 1 по 3 предназначены для конфликтующих объединений. Есть несколько специальных битов для маркировки удаленных файлов, или --assume-unchanged
, --skip-worktree
, --intent-to-add
и некоторые специальные внутренние флаги использования, и, хотя Git не хранит каталоги, есть записи индекса для каталогов (которые позволяют Git просматривать ctime
поле каталога, которое затем позволяет Git быстро пропускать неизмененные каталоги, при условии, что он может доверять ОС для поддержки этого).
git mktree
Команда вступает в действие только при преобразовании индекса в серию древовидных объектов. Git должен создать одно дерево для каждого подкаталога в индексе, плюс одно дерево верхнего уровня, представляющее общий индекс. (Подпроекты, если таковые существуют, уже включены в индекс как записи "gitlink", как они выглядят в любом дереве, в котором они содержатся.)