User Tools

Site Tools


kg:doc_devenv_mercurial

Меркуриал и что с ним делать

Общее

Меркуриал - распределенная система управления версиями (DVCS). Написана на питоне и потому работает везде и легко расширяется. Лучший друг и помощник разработчика, который понимает что с ней можно делать.

Термин “распределенность” зачастую понимается неправильно. В данном случае это не означает отсуствие главной репо, а лишь то, что изначально работа ведется с локальной (обычно дочерней) репо и не для своего функционирования не требует доступности родительской. Меджу репо существуют зависимости в виде DAG, но для упрощения работы обычно ограничиваются древообразной структурой получаемой клонированием родительской. В целом же, “распределенность” больше относится к свободе перемещения changeset'ов в этой иерархии.

Нужно помнить, что любая DVCS система куда более мощный инструмент нежели их далекие предки в виде CVS и SVN (Preforce, clearcase etc), которые в силу функциональных ограничений и юзабилити использовались максимум как удаленный способ хранения “снимка” рабочей копии и доставки последних изменений в оную от других пользователей. В этом разрезе mercurial предоставляет свободу выбора наиболее подходящего конкретному процессу разработки workflow. Впрочем, эта же свобода является и камнем преткновения, причиной крутой learning curve.

Прямым следствием является необходимость подумать, прежде чем что то сделать. Еще раз - dvcs это не дропбокс и не расшареный каталог “с историей”. Нужно представлять что ты хочешь сделать в терминах истории и changeset'ов. Только этим можно достигнуть светлой стороны силы!)

Правила хорошего тона

Банальности, но все же.

  • Не хранить индивидуальные файлы в репо. Всяческие настройки среды, пересоздаваемые файлы проекта (например как в эклипсе)
  • Не хранить производные файлы в репо. Если это можно получить из исходных, оно должно из них получатся. Исключение - если процесс их генерации сложен, требует внешнего инструментария и сами подконтрольные файлы изменяются редко.
  • ( Следствие из первого и второго ) По умолчанию прописывать в фильтр (.hgignore) все временные производные ( отладачная инфа, продукты компиляции, бэкапы итп )
  • Дважды подумать прежде чем добавить любой бинарный файл. Бинарники толком не версифицируются, не мержатся и кушают ваше время на пересылку. Лучшее решение для работы с большим объемом зависимых ассетов - хранить их отдельно в общем хранилище и вытаскивать нужную версию при помощи уже версифицируемого ( в репо ) скрипта или расширения. Исключения - личные репо, мелкие единичные бинарники которые проще покласть и забыть.
  • Внятные коментарии к изменениям - залог хорошей кармы.
  • Сломал - почини. Во всех workflow общие бранчи и репо должны содержать рабочий tip. Если нужно перетащить текущие наработки с одного места в другое ( с работы домой например ) - сделай форк. (Вообще это не совсем так. В отсуствие приватных бранчей (как у git) множить сущности в общей репе не рекомендуется. Мусор лучше хранить в своей копии репы)
  • Коммит changeset'а - это квант истории. Соответственно он должен означать некотурую логическую точку развития. Частота создания changeset'ов напрямую зависит от задачи. Общее правило : одна (под)задача - один коммит. Более масштабные изменения идут в бранчи ( впрочем, это зависит от workflow )

Еще немножко о зависимостях

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

Для решения этой проблемы в меркуриале существует расширение для организации зависимостей между репами. С его помощью легко организовать репозиторий так, что клонировании или обновлении рабочей копии в соседний или вложенный каталог вытаскивались и зависимости из своих собственных репо. Причем зависимые репо даже не должны быть меркуриалом, т.к. поддерживаются svn, cvs и другие git'ы. Более того, этим же расширением достигается и другой, немаловажный момент, а именно - фиксация зависимых версий. Иными словами, при инициализации зависимости сохраняется конкретная ревизия, которую мы утянули и эта ревизия версифицируется вместе с содержимым главной репо. Таким образом а) мы не подверженны внезапным breaking changes когда сторонние разработчики внезапно обновляют зависимый проект. б) так же, при желании мы можем обновить зависимость до новой версии и убедится что это все будет работать. с) мы не храним своей локальной копии и все зависимости утягиваются прямиком из первоисточника.

Настройка

Бинарный билд для вашей платформы легко гуглится. В домашнем каталоге появляется файл конфигурации ( win - %USERDIR%\Mercurial.ini, linux - ~/.hg/hgrc ) В котором необходимо поправить следующее:

  • Логин / мыло в указанном формате
  • Раскомментировать необходимые расширения
  • Настроить тулзу для мержа

Базовые операции

Смотрите маны

Операции специфичные для DVCS

Помимо обычных операций, свойственных обычным системам контроля версий, в современных dvcs доступны новые, облегчающие работу разработчика операции. Вот некоторые из них.

Горизонтальные версии

В меркуриале имеется в наличие несколько встроенных и внешних расширений, позволяющих производить обмен changeset'ов между разработчиками без изменения истории общей центральной репо. Это используется, например, если разработик хочет проверить некоторую идею и потом посмотреть как это повлияет на версию которой занимается другой член команды. Пофиксить некий (не сильно критичный баг) и отдать фикс товарищу. Или скажем в процессе работы над некоторой проблемой откатить изменения, обновить рабочую копию нужной версией и накатать свои изменения поверх нее. Тут очень много различных ситуаций которые становятся понятный в процессе работы.

Традиционно эти вопросы ( особенно с локальным обменом изменениями ) решались посредством создания временных бранчей основной репо ( или ее копиями ). В первом случае происходило замусоривание репозитория, ведь любая система управления версиями не позволяет (простыми средствами) модифицировать историю и убивать побочные ветки. Во втором случае проблемы возникали с ручным созданием и расшариванием тех самых копий репозитория, усугубляя сложностями мержа его в основную.

Указанная функциональность обеспечивается посредством расширений: mq, pbranch, attic, shelf итп

Машина времени или манипуляции с историей

В практике работы с VCS встречается масса ситуаций когда стандартные средства дают неудовлетворительные результаты. К примеру - проблема засорения главной истории мелкими changeset'ами, в т.ч. результатами мержа, в то время когда хотелось бы чтоб в истории фигурировали только атомарные, реализующие конкретную фичу или убивающие конкретный баг вехи.

Светлой стороне силы DVCS доступна возможность избавится от подобных артефактов. Главным помощником разработчика в этом является встроенная ( пришедшая из git ) комманда rebase. С ее помощью можно, например, объединить все changeset'ы локального бранча и накатить их поверх tip'а. Или же, в процессе работы ( и серии коммитов ) над фичей, принять изменения и переместить все свои наработки поверх текущей версии. И еще много чего.

Более детальное объяснение см. в секции Advanced workflow.

Workflow

Практики (workflow) - описывают процессы взаимодействия разработчиков с репозиториями, общие правила работы. Поскольку они зависят от конкретного проекта и культуры разработки, конкретная практика зачастую вынашивается в процессе разработки, что, впрочем, не мешает знать хотя бы какие они бывают.

Поэтапный процесс

[ Production repository ] содержит от-tag'еные релизы. 
     ^ ^ ^ ^ ^ ^ ^ 
[ Staging/demo repository ] содержит пред-релизные версии для конечного тестирования, только из нее можно отправить версию в продакшен
     ^ ^ ^ ^ ^ ^ ^
   [ QA repository ] промежуточные результаты интеграции, версии для QA тима и автоматизированного тестирования
        ^ ^ ^ ^
      [ Dev repo ]  общий репозиторий текущей версии в разработке, с ней взаимодействуют только разработчики. Это место для стабильных версий.
      
  1. Продакшен - это доступная в любое время стабильная, протестированная итп версия, которую можно взять и отдать клиенту. Обновляется самым главным вручную по результатам из staging/demo.
  2. Staging/demo - протестрованная насколько можно, готовая к выкладыванию в боевые условия версия. Отсюда можно всегда взять нечто готовое, свежее и показать. (Что то вроде PTR.) Обновляется раз в сутки по результатам тестирования из QA репы и необходимости этого обновления (демонстрация, промежуточные-релизы итп)
  3. QA - собранная версия подготовленная для (автоматического) тестирования. В нее раз в сутки или по некоторому условию сливаются результаты работы из development репы. С ней работают тестеры.
  4. Dev - общие результаты работы ежедневно. Ест-но в ней не должно появлятся поломаных версий, т.е. коммит в нее производится только после удачной сборки и некоего минимального набора тестов.

Централизованная с побочным хранилищем (патчей)

Одна главная репа с отмечеными продакшен релизами и бранчами для минорных / мажорных версий. Пример - в главном бранче живет текущая живая версия, от нее отпочковываются по мере релизов мажорные и соответственно от мажорных - минорные версии. Готовые релизы помечаются тэгами в соответствующих бранчах. Дополнительно разработчики используют attic/mq/shelve расширение с отдельной общей репо для хранения и обмена патчами. Этим способом организуется возможность:

  • написать, оттестировать отдельную feature локально не загрязняя главную репу
  • обменяться патчем (фичей) разработчикам ( эй, петя, а попробуй в своей версии мой супер быстрый блиттер )
  • всегда сохранять результаты работы ( даже промежуточные ) удаленно

На PBranch

Совместная работа с унаследованной CVS / SVN репо

Работа с Patch Queue

С отслеживанием изменяемых snapshot'ов

Advanced workflow

Социальные сайты - репозитории

На примере bitbucket'а. Каковы преимущества по сравнению с home-brewed решением?

  • Простота управления репозиториями, в т.ч. правами доступа (пара кликов в веб интерфейсе)
  • Надежность хранилища (потеря локальной машины или хостинга куда более вероятна)
  • Встроенные средства мониторинга изменений ( мне на телефон прилетают сообщения о каждом коммите )
  • Встроенные средства баг-треккинга
  • Встроенные средства для организации документации
  • Поддержка последних фич, в т.ч. mq ( patch queue )
  • Невыносимая легкость создания форков ( одна кнопка и я работаю со своей приватной версией, не трогая соседа )
  • Халява! ( Битбакет дает сколько хочешь всего и даже приватные репы на тим до 5 разработчиков )

Ссылки по теме

kg/doc_devenv_mercurial.txt · Last modified: 2012/01/31 10:25 (external edit)