В нашем блоге на Хабре мы рассказываем о различных технологиях из мира IaaS и не только. Например, недавно мы публиковали материал по программным реализациям VPN [Часть 1; Часть 2], а также рассказывали о DNS. Сегодня нам бы хотелось углубиться в тему разработки приложений и сервисов и поговорить о такой вещи, как Git, в частности, о способах оптимизации работы с ним.


/ фото hackNY.org CC


Хотелось бы начать с самого начала – что же такое Git? Git – это одна из систем управления версиями (version control system, или VCS), на основе которой построены несколько сервисов, таких как GitHub или GitLab. С помощью Git было разработано большое количество программного обеспечения, которое, вероятно, вам хорошо знакомо: это и ядро Linux, Firefox, а также Chrome.

Если вы работали в команде над каким-нибудь программным продуктом, то представляете, как все происходит. У вас имеется определенная версия вашего проекта, которую вы отправляете своим коллегам. Они вносят изменения в код и отсылают их обратно. Вы же встраиваете их в свою кодовую базу и получаете новую версию проекта.

Одна из основных задач Git – избежать ситуации c путаницей между версиями продукта, когда появляются файлы с именами вроде project_betterVersion.kdenlive или project_FINAL-alternateVersion.kdenlive и т. д.

Чтобы упростить работу с этими файлами и нужны системы VCS. Так каждый член команды имеет возможность работать над последней версией проекта, вносить свои изменения и сообщать об этом коллегам.

Системы контроля позволяют хранить несколько вариаций одного и того же документа и при необходимости «откатывать» его до более ранней реализации. То есть вы можете сделать копию репозитория и работать с ней локально, а затем при помощи специальных команд внедрить свои правки (push) в основную версию или извлечь (pull) изменения, сделанные коллегами.

Повышение производительности


При работе над большими продуктами постоянно происходит переименование исходников, выделение новых веток, выполняется сравнение с прошлыми версиями. Потому в достаточно больших проектах может наблюдаться снижение производительности работы Git. С такими проблемами как-то раз столкнулась даже компания Facebook.

Тогда сложности в работе они объяснили тем, что при любом изменении исходных файлов происходило переписывание индексного файла, а в большом проекте его размер превышал 100 МБ. Это и привело к замедлению работы (кстати, вот одно интересное решение уже другой проблемы с производительностью систем управления версиями Facebook, предложенное инженерами компании).

Чтобы ускорить работу с Git, разработчиками применяются различные техники, утилиты и решения. Одним из вариантов может быть уменьшение размеров репозитория.

Уменьшение репозитория


RoR-разработчик Стив Лорек (Steve Lorek) в своем блоге пишет о том, что ему удалось сократить размер репозитория с 180 МБ до 7 МБ. Для этого он сперва создал локальную копию Git, а затем нашел файлы, занимающие слишком много места в хранилище. Здесь на помощь пришел bash-скрипт Энтони Стаббса (Antony Stubbs), который находит 10 самых крупных и ненужных файлов.

После этого он удалил эти файлы, воспользовавшись серией команд:

$ git filter-branch --tag-name-filter cat --index-filter 'git rm -r --cached --ignore-unmatch filename' --prune-empty -f -- --all
$ rm -rf .git/refs/original
$ git reflog expire --expire=now –all
$ git gc --prune=now
$ git gc --aggressive --prune=now

После этого Стив отправил изменения в удаленный репозиторий, чтобы больше никому не пришлось скачивать для работы 180 мегабайт.

Умное зеркалирование


Это еще одно решение, которое пригодится организациям, насчитывающим несколько сотен разработчиков. Многие члены таких команд работают удаленно и из разных стран, что приводит к задержкам при загрузке данных из репозиториев. Бывает доходит до того, что сотрудники пересылают друг другу жёсткие диски по почте.

При зеркалировании настраивается один или несколько активных зеркальных серверов, которые исполняют только операции чтения копий репозиториев и синхронизируются с основным экземпляром. Такой подход позволяет сократить время передачи копии репозитория на 5 ГБ примерно в 25 раз.

Иной подход к хранению крупных файлов


Из-за того что каждый разработчик хранит на своем компьютере всю историю изменений, размер репозиториев Git растет быстро. Однако есть ряд утилит, решающих эти проблемы. Например, git-annex позволяет хранить вместо целого файла символьную ссылку (symlink) на него.

Также стоит отметить расширение Git Large File Storage (Git LFS), которое пишет в репозиторий указатели на файлы. Операции с этими файлами отслеживаются с помощью фильтров clean и smudge, а их содержимое хранится на удаленном сервере GitHub.com или GitHub Enterprise. Описание нескольких других утилит вы можете найти по ссылке.

Использование псевдонимов


Этот совет связан не столько с производительностью Git и скоростью загрузки файлов, сколько с удобством работы. Определение псевдонимов способно значительно повысить скорость работы с Git и упростить множество операций. Псевдонимы настраиваются с помощью файла конфигураций:

git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status

Интересно, что таким образом можно создавать собственные команды, которых по умолчанию нет в системе, например:

git config --global alias.l "log --oneline --graph"

Конкретно в этом случае вы получите возможность выводить логи в строчку и в графическом виде командой git l.

Эти небольшие советы могут помочь упростить работу с большими репозиториями и облегчить жизнь командам разработчиков. А это большое дело в плане качества и скорости выполнения важных проектов компании.

P.S. А еще мы пишем о создании нашего IaaS-провайдера 1cloud:

Поделиться с друзьями
-->

Комментарии (12)


  1. Cheater
    20.09.2016 14:50

    Я бы ещё добавил sparse checkout.


  1. Radiocity
    20.09.2016 15:06
    -1

    Разве rm -rf не вызывается без дополнительных параметров во всех случаях работы с git?


  1. almassar
    20.09.2016 15:06
    -2

    а как одной командой сделать add, commit и push, причем в коммит нужно еще написать сообщение?


    1. farcaller
      20.09.2016 16:15

      function acp() { git add . && git commit -am "$1" && git push; } ?


    1. valery1707
      20.09.2016 16:26

      Команда git commit -a -m 'Commit message' выполнит добавление файлов и коммит с комментарием.
      Если хочется сюда добавить ещё и push, то можно создать свой псевдоним


    1. el777
      20.09.2016 17:41
      +3

      Вы бросайте эти SVN-замашки :)
      На самом деле стоит немного потратить времени на изучение git, и его вариант с раздельными командами покажется более правильным.


      1. almassar
        22.09.2016 18:02

        согласен с вами. просто часто бывает когда фиксишь маленькую вещь, хочется быстрее отправить ее в гит


        1. G-M-A-X
          22.09.2016 21:13

          1. Кто спешит, тот людей смешит. :)
          2. Пользуйтесь нормальной IDE с горячими клавишами. :)


  1. ALexhha
    20.09.2016 18:48

    Я бы ещё добавил sparse checkout.

    Я правильно поимаю, что sparse checkout по прежнему "тянет" полную историю (в папке .git)? Т.е. если у вас репозитарий занимает 1 Гб, а вам надо было скачать папку в 100 Кб, то sparse checkout скачает все равно 1 Gb.


    Насколько я знаю у git нет аналога svn checkout, когда ты можешь скачать любую папку(бранч) и работать с ней, что в некоторых случаях является очень удобным, особенно при условии хранения бинарных данных (картинок)


    1. 3lnc
      21.09.2016 11:14

      Возможно я не совсем понимаю желаемое, но есть
      ```bash git clone --depth X ...```
      какой клонирует репу с указанной глубиной истории. Укажите 1 и получите shallow copy. Многие так делают при деплойменте и на CI/CD серверах.


      1. ALexhha
        21.09.2016 16:48

        Допустим у вас есть ветка dev со след структурой

        /
        |-src
        |-test
        |-images
        

        и вам необходимо скачать только папку src, так как images занимает 1 Гб. Вы сможете это сделать в git?


        1. bohdan4ik
          22.09.2016 17:43

          Но это же не gitиоматично, хранить двоичные файлы в git.

          Если есть нужда хранить большое количество бинарников — на сегодня есть git lfs.