Релиз распределенной системы управления исходными текстами Git 2.11.0
Представлен выпуск распределенной системы управления исходными текстами Git 2.11.0. Git является одной из самых популярных, надёжных и высокопроизводительных систем управления версиями, предоставляющей гибкие средства нелинейной разработки, базирующиеся на ответвлении и слиянии веток. Для обеспечения целостности истории и устойчивости к изменениям задним числом используются неявное хеширование всей предыдущей истории в каждом коммите, также возможно удостоверение цифровыми подписями разработчиков отдельных тегов и коммитов. Из проектов, разрабатываемых с использованием Git, можно отметить ядро Linux, Android, LibreOffice, Systemd, X.Org, Wayland, Mesa, GStreamer, Wine, Debian, DragonFly BSD, Perl, Eclipse, GNOME, KDE, Qt, Ruby on Rails, PostgreSQL, VideoLAN, PHP, Xen, Minix.
По сравнению с прошлым выпуском в новую версию принято 673 изменения, подготовленных при участии 74 разработчиков, из которых 15 впервые приняли своё участие в разработке. Основные изменения:
- Переработан алгоритм формирования сокращённой формы отображения идентификаторов объектов. Так как полный хэш SHA-1 состоит из 40 шестнадцатеричных цифр и достаточно трудно воспринимается пользователем, в git активно применяется сокращённая система отображения, которая значительно упрощает ввод идентификаторов различных объектов. Чтобы избежать коллизий, приводящих к ссылкам сокращённой формы на более чем один объект в репозитории, до сих пор в Git применялся адаптивный алгоритм формирования идентификатора — вначале формируется 7-символьное представление хэша, которое оставляется если в репозитории нет других объектов с таким идентификатором, и доводится до 8- или 9-символьного варианта в случае обнаружения пересечений.
Для 7-символьных имён коллизии начинают проявляется в репозиториях, содержащих десятки тысяч объектов. В репозитории с ядром Linux, насчитывающем 5 млн объектов, коллизии наблюдаются для идентификаторов, размером менее 12-символов. Применяемый подход обладает существенным недостатком: отсутствие коллизии в текущий момент не исключает их появление для объектов, которые будут добавлены в будущем. В небольших репозиториях вероятность появления отложенной коллизии невелика, но становится вполне ощутимой в больших и динамично развиваюзщихся репозиториях. Например, опубликованный в системе отслеживания ошибок идентификатор со временем может начать указывать на несколько объектов.
В Git 2.11.0 существенно расширены средства для проверки пересечений при выполнении операций. Минимальный размер сокращённого идентификатора теперь не фиксирован и динамически выбирается в зависимости от числа объектов в репозитории. Кроме того, если в команде задан слишком короткий идентификатор, для которого в репозитории присутствует несколько объектов, кроме предупреждения о выявлении конфликта, в git 2.11 будет выведен список пересекающихся объектов с дополнительной информацией, достаточной для того чтобы уточнить, какой из более длинных идентификаторов выбрать. Информация в списке выводится с учётом контекста — в первую очередь показываются более вероятные кандидаты объектов, например, в «git log» в первую очередь показываются коммиты. Для выбора первичных типов для других команд, таких как «git show», предложена новая опция «core.disambiguate».
- Ускорен доступ к delta-цепочкам в базе объектов, что положительно сказалось на производительности многих типовых операций. Delta-цепочки служат для объединения дубликатов при хранении файлов с частично совпадающим содержимым. Для эффективного хранения пересечений один из объектов выбирается как базовый, а похожие на него другие объекты оформляются в виде delta — набора инструкций, определяющих имеющиеся изменения. Так как базовый объект со временем может меняться, в качестве основы для других объектов могут выступать delta-изменения, образуя таким образом delta-цепочки (версия 2 сохраняется как delta от версии 1, а версия 3 как delta от версии 2 и т.п.).
Чем глубже уровень вложенности, тем больше требуется ресурсов для реконструкции содержимого объекта. В режиме агрессивной упаковки «git gc --aggressive» ранее допускалось создание вложенных цепочек, включающих до 250 объектов, но так как при размере цепочки в более 50 объектов разбор становится неэффективным с точки зрения нагрузки на CPU, по умолчанию максимальный уровень вложенности в Git 2.11 ограничен 50 объектами. Для сокращения нагрузки также полностью переработана реализация кэша недавно восстановленных объектов, что позволило примерно на 10% ускорить работу в больших репозиториях. Для дальнейшего повышения эффективности можно увеличить размер кэша через опцию core.deltaBaseCacheLimit, которая по умолчанию установлена в 96 Мб (например, при увеличении до 1 Гб скорость работы с репозиторием ядра Linux возросла на 32%);
- Увеличена производительность поиска объектов, в условиях наличия нескольких pack-файлов в репозитории. При большом числе объектов, Git упаковывает группы объектов в сводные pack-файлы, включающие также индексы для быстрой выборки. Новые pack-файлы могут появляться при извлечении или приёме изменений по сети, что приводит к постепенному увеличению числа pack-файлов в репозитории до тех пор, пока не будет инициирована операция переупаковки репозитория. Несмотря на то, что разбор отдельного pack-файла достаточно быстрая операция, при наличии большого числа pack-файлов поиск нужного объекта превращается в последовательный перебор pack-файлов.
Частично проблема решалась через кэш, определяющий привязку объектов к pack-файлам, а в git 2.10 дополнительно был применён более эффективный метод, перебирающий pack-файлы в порядке прошлого обращения к ним. В Git 2.11 сделан ещё один шаг и новая стратегия перебора задействована при выполнении операции переупаковки. Например, внесённые изменения позволили на 70% ускорить переупаковку репозитория с ядром Linux, в котором накопилось 1000 pack-файлов;
- Увеличена производительность вычислений идентификаторов патчей (patch ID), активно применяемых при выполнении операции «git rebase». Идентификатор патча представляет собой хэш от изменений, внесённых в рамках одного коммита, что позволяет выявлять дубликаты коммитов и избегать операций переименования и слияния коммитов. В Git 2.11 скорость проверки дубликатов на основе идентификаторов патчей в некоторых ситуациях возросла до 50 раз;
- Реализован новый протокол для организации запуска фильтров, используемых для преобразования содержимого файла в представление локальной файловой системы. В том числе через фильтры можно подключить собственный обработчик, вызываемый при операциях с Git LFS. Старый протокол, подразумевал запуск отдельного процесса для обработки каждого файла, что при наличии большого числа файлов приводило к большим накладным расходам из-за запуска большого числа процессов, а также ограничивало возможности совместного использования ресурсов между разными экземплярами фильтра.
Добавленный в Git 2.11 новый протокол позволяет организовать цикличную обработку разных файлов в одном процессе. В некоторых ситуациях в репозиториях с большим числом объектов в Git LFS, новый протокол позволяет увеличить скорость применения фильтра в 80 раз. В будущем планируется расширить новый протокол поддержкой выполнения фильтров в асинхронном режиме. Поддержка старого протокола сохранена для обеспечения обратной совместимости;
- На основе замечаний о работе экспериментальной опции »--compaction-heuristic», включающей дополнительную эвристику для корректного отображения логики изменений, в которых фигурируют повторяющиеся блоки, в Git 2.11 представлен улучшенный алгоритм компоновки отступов. Новый алгоритм доступен через опцию »--indent-heuristic» (настройка diff.indentHeuristic) и возможно будет активирован по умолчанию в одном из следующих выпусков Git;
- Добавлена поддержка метки »^-1» для исключения показа изменений, уже имеющихся в ветке до выполнения операции слияния. Например, «git log 1234abcd^-1» покажет все коммиты, которые были приняты при слиянии с веткой 1234abcd, но не отобразит уже имеющиеся в ветке коммиты;
- В contrib/ добавлен модуль для хранения паролей Git при помощи GNOME libsecret;
- В команду «git diff» добавлена опция »--submodule=diff», при которой будут показаны изменения субмодулей в форме патча между двумя состояниями субмодуля;
- В «git status» реализован новый машиночитаемый формат вывода для упрощения автоматизированного разбора данных;
- С целью увеличения производительности продолжена работа по замене shell-скриптов Git на программы на языке Си.
© OpenNet