Скотт Чакон - Pro Git
- Название:Pro Git
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Скотт Чакон - Pro Git краткое содержание
В книге рассматриваются следующие темы: основы Git;
ветвление в Git;
Git на сервере;
распределённый Git;
GitHub;
инструменты Git;
настройка Git;
Git и другие системы контроля версий.
Pro Git - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Для начала найдём проблемный файл. В данном случае, мы заранее знали, что это за файл. Но если бы не знали, как можно было бы определить, какие файлы занимают много места? При вызове git gc все объекты упаковываются в один pack-файл, но, несмотря на это, определить самые крупные файлы можно, запустив служебную команду git verify-pack, и отсортировав её вывод по третьей колонке, в которой записан размер файла. Так как нас интересуют самые крупный файлы, оставим три последние строки с помощью tail:
$git verify-pack -v .git/objects/pack/pack-29…69.idx \
| sort -k 3 -n \
| tail -3
dadf7258d699da2c8d89b09ef6670edb7d5f91b4 commit 229 159 12
033b4468fa6b2a9547a70d88d1bbe8bf3f9ed0d5 blob 22044 5792 4977696
82c99a3e86bb1267b236a4b6eff7868d97489af1 blob 4975916 4976258 1438
Большой объект в самом внизу, его размер — 5 МБ. Для того чтобы узнать, что это за файл, воспользуемся командой rev-list, которая уже упоминалась в главе Enforcing a Specific Commit-Message Format. Если передать ей ключ --objects, она выдаст хеши всех коммитов, а также хеши объектов и соответствующие им имена файлов. Воспользуемся этим для определения имени выбранного объекта:
$git rev-list --objects --all | grep 82c99a3
82c99a3e86bb1267b236a4b6eff7868d97489af1 git.tgz
Теперь необходимо удалить данный файл из всех деревьев в прошлом. Легко получить все коммиты, которые меняли данный файл:
$git log --oneline --branches -- git.tgz
dadf725 oops - removed large tarball
7b30847 add git tarball
Необходимо переписать все коммиты, начиная с 7b30847 для полного удаления этого файла из истории. Воспользуемся командой filter-branch, о которой мы писали в Исправление истории:
$git filter-branch --index-filter \
'git rm --ignore-unmatch --cached git.tgz' -- 7b30847^..
Rewrite 7b30847d080183a1ab7d18fb202473b3096e9f34 (1/2)rm 'git.tgz'
Rewrite dadf7258d699da2c8d89b09ef6670edb7d5f91b4 (2/2)
Ref 'refs/heads/master' was rewritten
Опция --index-filter похожа на --tree-filter, использовавшуюся в главе Исправление истории, за исключением того, что вместо передачи команды, модифицирующей файлы на диске, мы используем команду, изменяющую файлы в индексе.
Вместо удаления файла чем-то вроде rm file, мы используем git rm --cached, так как нам надо удалить файл из индекса, а не с диска. Причина, по которой мы делаем именно так — скорость: нет необходимости извлекать каждую ревизию на диск, чтобы применить фильтр, а это может очень сильно ускорить процесс. Если хотите, можете использовать и tree-filter для получения аналогичного результата. Опция --ignore-unmatch команды git rm отключает вывод сообщения об ошибке в случае отсутствия файлов, соответствующих шаблону. Ещё один момент: мы указали команде filter-branch переписывать историю, начиная с коммита 7b30847, потому что мы знаем, что именно в этом изменении впервые появилась проблема. По умолчанию перезапись начинается с самого первого состояния, что потребовало бы гораздо больше времени.
Теперь история не содержит ссылок на данный файл. Однако, в reflog и в новом наборе ссылок, добавленном Git в .git/refs/original после выполнения filter-branch, ссылки на него всё ещё присутствуют, поэтому необходимо их удалить, а потом переупаковать базу. Необходимо избавиться от всех возможных ссылок на старые коммиты перед переупаковкой:
$rm -Rf .git/refs/original
$rm -Rf .git/logs/
$git gc
Counting objects: 15, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (15/15), done.
Total 15 (delta 1), reused 12 (delta 0)
Проверим, сколько места удалось освободить:
$git count-objects -v
count: 11
size: 4904
in-pack: 15
packs: 1
size-pack: 8
prune-packable: 0
garbage: 0
size-garbage: 0
Размер упакованного репозитория сократился до 8 КБ, что намного лучше, чем 5 МБ. Из значения поля size видно, что большой объект всё ещё хранится в одном из ваших "рыхлых" объектов, но, что самое главное, при любой последующей отправке данных наружу (а значит и при последующих клонированиях репозитория) он передаваться не будет. Если очень хочется, можно удалить его навсегда локально, выполнив git prune --expire:
$git prune --expire now
$git count-objects -v
count: 0
size: 0
in-pack: 15
packs: 1
size-pack: 8
prune-packable: 0
garbage: 0
size-garbage: 0
Переменные среды
Git всегда запущен в bash и использует некоторые переменные shell среды, чтобы определить, как она себя ведет. Порой удобно знать, какие именно константы используются, чтобы Git работал именно так, как вы хотите. Это не исчерпывающий список переменных среды, которые использует Git, но мы рассмотрим самые полезные.
Глобальное поведение
Поведение Git как компьютерной программы зависит от параметров среды.
GIT_EXEC_PATHопределяет где Git будет искать свои подпрограммы Текущие настройки можно узнать командой git --exec-path.
HOMEобычно не рассматривается в качестве изменяемого параметра (чересчур много вещей от него зависят), но именно тут Git ищет глобальный файл конфигурации. Если вам нужна по-настоящему portable-версия Git с собственной глобальной конфигурацией, можете переопределить HOME в shell профиле.
PREFIXаналогичная константа, но для общесистемной конфигурации. Git ищет этот файл в $PREFIX/etc/gitconfig.
GIT_CONFIG_NOSYSTEM, если задана, отключает использование файла общесистемной конфигурации. Это пригодится, если ваша системная конфигурация мешает вашим командам, а прав на её редактирование или удаление у вас нет.
GIT_PAGERопределяет программу, используемую для отображения многостраничного вывода в командной строке. Если не задана, в качестве запасного варианта используется PAGER.
GIT_EDITORэто редактор, который Git запустит, когда пользователю понадобится отредактировать какой-нибудь текст (например, сообщение коммита). Если не задана, откроется EDITOR.
Расположение репозитория
Git использует некоторые переменные среды, чтобы определить как она взаимодействует с конкретным репозиторием.
GIT_DIR— это месторасположение директории .git. Если эта переменная не задана, Git будет переходить вверх по дереву директорий, пока не достигнет ~ (домашней директории пользователя) или / (корневой директории), проверяя на каждом шагу наличие директории .git.
GIT_CEILING_DIRECTORIESуправляет процессом поиска директории .git. Если вы работаете с медленной файловой системой (типа ленточного накопителя или сетевой папки), вы можете запретить Git доступ к .git без надобности, например, для построения строки приветствия.
GIT_WORK_TREE— это путь к рабочей директории для не-серверного репозитория (с непустой рабочей директорией). Если эта переменная не задана, будет использована родительская директория $GIT_DIR.
GIT_INDEX_FILE— это путь к файлу индекса (только для репозиториев с непустой рабочей директорией).
GIT_OBJECT_DIRECTORYможет быть использована для указания директории с объектами вместо .git/objects.
GIT_ALTERNATE_OBJECT_DIRECTORIES— это список разделённых двоеточием директорий (типа /dir/one:/dir/two:…), в которых Git будет пытаться найти объекты, которых нет в GIT_OBJECT_DIRECTORY. Это может быть полезным, если вы работаете над несколькими проектами с одинаковым содержимым, чтобы не дублировать файлы.
Читать дальшеИнтервал:
Закладка: