#git
Сегодня пришлось задуматься о том, как гит хранит историю?
Вопрос очень простой, скажем я создал проект, сложил в него очень тяжелые файлы(2
гб) и сделал коммит. Потом я эти файлы удалил и у меня и сделал еще коммит. Но я могу
вернуться на предыдущий коммит и получить эти файлы обратно, верно? Значит из этого
следует, что при удалении файлов, гит все равно хранит их копии, а значит вес проекта
(самой папки) и занимаемое ей место при удалении тяжелых файлов не уменьшиться?
Но мне почему то не кажется, что когда я делаю клон ветки прокта, что я получаю всю
историю (скажем прошлые коммиты и тяжелые файлы 2гб в нашем примере) во всяком случае
локально в файлах на компе их нет.
Но ведь история коммитов у меня есть, а значит и все файлы должны быть сохранены(как
то, где то)...
Короче, что то тут не сходиться.
Вопрос в том, действительно ли храняться все копии файлов? А если проекту 10 лет
и за это время уже миллион файлов(и их вес) были удалены они, что до сих пор где то
в гите храняться?
Ответы
Ответ 1
Гит все равно хранит их копии, а значит вес проекта (самой папки) и занимаемое ей место при удалении тяжелых файлов не уменьшиться Да, верно. Проверим: # так смотрим размер каталога .git du -hs .git # так можно сделать файл 1Мб dd if=/dev/zero of=filename bs=1M count=1 пустой проект 104 Кб после коммита файла filename в 1Мб вес .git 164 Кб (гит сжимает данные) после удаления файла filename и коммита - 180 Кб Но мне почему то не кажется, что когда я делаю клон ветки прокта, что я получаю всю историю Это вам только кажется А если проекту 10 лет и за это время уже миллион файлов(и их вес) были удалены они, что до сих пор где то в гите храняться? Да Как можно уменьшить размер .git каталога: запустить git gc --aggressive, но он пропылесосит только ненужные файлы, и пережмет данные, но файл filename так и останется в репо, но место освободилось: стало 152Кб переписать историю через git rebase: что-то удалить, что-то слить выкачивать репо без всей истории: git clone --depth 1 ... скачает историю на глубину 1 Для хранения больших файлов (мультимедиа) лучше использовать Git Large File Storage git gc Это служебная команда оптимизации "базы данных гита". Какие-то объекты в этой базе становятся недостижимыми (столкнетесь при большем погружении в гит, они появляются при "переписывании истории") - они удаляются. Данные пережимаются, ведь индекс в процессе эксплуатации становится не совсем оптимальным, вот он и "перестраивается". С самим репозиторием, как это видно "внешне", при вызове git gc ничего не происходит, вся история остается на месте. если я локально чищу .git, то синхронизируются ли эти изменения с удаленным репо? через git gc - нет, эта команда для локального применения, она оптимизирует локальный репо, смысла делать ее перед push совершенно нет, удаленный репо имеет "свой мусор", и чистить удаленный репо можно только путем захода на удаленный сервер и запуска git gc в bare-репо если вы комитили, комитили, и наконец, перед push (это крайне важно!!!) решили сократить размер репо - используйте git rebase: путем объединения коммитов вы "почтистите историю" (в первом коммите огромный файл был, а во втором его удалили) - при пуше в удаленный репо этот огромный файл передаваться не будет, это главное. А в локальном репо размер .git после rebase вырастет - на "историю rebase". И тот огромный файл в каталоге .git также останется в виде сжатого объекта, хотя и недоступного (так как вы поменяли историю). А вот запуск git gc теперь удалит из .git этот файл и из вашего локального репо правда я так понимаю, что они не идентичны так как удалено находится bare repo Правильно понимаете. А для распределённой системы управления версиями, которой является git, "клонированный" может быть точь-в-точь как "удаленный" только в момент клонирования. Дальше, по мере появления коммитов, на уровне байтов они начинают расходиться все больше. История может и будет совпдать, но каталог .git - нет. По сути .git - это база данных, и работать с ней нужно как с базой данных, а не на уровне файлов и байтов. git gc искусственно запускать также не нужно, git сам предложит это сделать, когда начнет работать медленно, и даже будет делать это самостоятельно, если стоит опция gc.auto 1.
Комментариев нет:
Отправить комментарий