@GSimonX37

Как в Git в организовано хранение файлов?

Помогите пожалуйста разобраться:
1. Я сделал коммит файла. После этого изменил его 3 раза и сделал 3 коммита. Git сохраняет первоначальную копию файла и все 3 его измененных копии полностью (т. е. если я в файле изменил всего 1 % данных он 99% просто дублирует в следующую копию), или хранит первоначальную копию и отдельно 3 последующих изменения (т. е. только то, чего нет в изначальной копии)?
2. Когда я переключаюсь с ветки на ветку, Git копирует в рабочий каталог файлы из базы данных. Я правильно понимаю, что он также при этом копирует те же самые файлы в индекс, так как Git понимает, что нету измененных файлов, сравнивая рабочий каталог с индексом?
3. И тоже самое происходит, когда я клонирую репозиторий? Сначала копируется база данных из удаленного репозитория, потом данные копируются в рабочий каталог и индекс?
  • Вопрос задан
  • 256 просмотров
Решения вопроса 2
saboteur_kiev
@saboteur_kiev Куратор тега Git
software engineer
Вообще-то как раз гит хранит целые копии файла.
Для каждого файла создается его хеш, и файл-объект хранится под именем с этим кешом.

If you again examine your objects directory, you can see that it now contains a file for that new content. This is how Git stores the content initially — as a single file per piece of content, named with the SHA-1 checksum of the content and its header. The subdirectory is named with the first 2 characters of the SHA-1, and the filename is the remaining 38 characters.


То есть любое изменение файла - создает еще один файл-объект.
Два одинаковых файла не будут занимать два места, даже если они хранятся под разными именами.

Каждый коммит - содержит список файлов и хеш для содержимого.
А ветка - это просто ссылка на конкретный коммит и немного метаданных.

Также файлы-объекты хранятся упакованными, а периодически файлы-объекты могут быть объеденены в отдельный пакет.

Чтобы посмотреть содержимое любого гит-объекта, юзай
git cat-file -p ID_объекта (где айди объекта это как раз его хеш)

И собственно именно эта фича - хранение каждого изменения файла отдельным объектом и позволило создать легковесные ветки, где переключение на любой коммит любой ветки - быстрая проверка и копирование файлов, в отличие от CVS и SVN, где любое переключение ветки - куча пересчетов диффов как назад так и вперед.

Но, поскольку SVN - централизированная система, где все изменения хранятся только на сервере, можно менять формат хранения между версиями, так как это не нужно согласовывать со всеми пользователями репозитория.
Например кроме диффов, в поздних SVN периодически сохраняются полные снепшоты, например каждые 1000 коммитов делается полный слепок, что ускоряет перерасчеты.
Ответ написан
AshBlade
@AshBlade
Просто хочу быть счастливым
1. Гит в истории целые файлы, уже измененные, но сжатые (изменения хранит SVN, но у него другая модель работы)
2. Сравнение файлов происходит через сравнение хэша файла. История изменений хранится в виде графа, поэтому переключение - это по сути: 1. Найти общего предка 2. Откатиться до этого предка 3. Применить изменения до новой ветки. Дополнительно, если у тебя есть незакоммиченные текущие изменения, то гит тебе об этом скажет
3. Скачивается вся история изменений из удаленного репозитория и потом HEAD выставляется на ветку, которую клонировал (в основном это main/master)

Почитай как работает git

UPD: спасибо Saboteur за важное замечание
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
OTCloud
@OTCloud
Программирование и Архитектура ПО
└─$ find .git                             
.git
.git/config
.git/info
.git/info/exclude
.git/HEAD
.git/refs
.git/refs/tags
.git/refs/heads
.git/branches
.git/hooks
.git/hooks/pre-rebase.sample
.git/hooks/post-update.sample
.git/hooks/pre-commit.sample
.git/hooks/pre-merge-commit.sample
.git/hooks/update.sample
.git/hooks/pre-receive.sample
.git/hooks/commit-msg.sample
.git/hooks/applypatch-msg.sample
.git/hooks/pre-applypatch.sample
.git/hooks/pre-push.sample
.git/hooks/push-to-checkout.sample
.git/hooks/prepare-commit-msg.sample
.git/hooks/fsmonitor-watchman.sample
.git/objects
.git/objects/info
.git/objects/pack
.git/description

Git Repository Layout
https://git-scm.com/docs/gitrepository-layout

objects
Хранилище объектов, связанное с этим репозиторием. Обычно хранилище объектов самодостаточно (т. е. все объекты, на которые ссылается найденный в нем объект, также находятся в нем), но есть несколько способов его нарушить.
- Вы можете получить неполный, но пригодный для локального использования репозиторий, создав поверхностный клон.
- Вы можете использовать механизмы objects/info/alternates или $GIT_ALTERNATE_OBJECT_DIRECTORIES для заимствования объектов из других хранилищ объектов. Репозиторий с таким неполным хранилищем объектов не подходит для публикации для использования с тупыми транспортами, но в остальном все в порядке, если objects/info/alternates указывают на хранилища объектов, из которых он заимствован.
...

и так далее.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы