Mercurial сатори

Скоро мне понадобится знакомить одного будущего молодого разработчика с таинством пользования системами контроля версий (далее VCS, version control system) и поэтому чтобы немного систематизировать то, что я собирался рассказать, решил написать это сообщение. Он рассчитан на совершенно базовый уровень работы и поэтому здесь много разжевываний, более опытным лицам вряд будут интересны. Знакомство сразу буду проводить на примере современных распределенных систем, в нашем случае Mercurial.

Зачем оно нужно?

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

Кстати, место где сберегаются все состояния проекта в терминах VCS называется репозитарий, а место в котором вы вносите правки — соответственно рабочая копия. Процесс отправки набора изменений с рабочей копии в репозиторий — это операция commit. Репозитарии часто хранят подальше, не на рабочих машинах, чтобы в випаку когда у вас, например, сдохнет комп, весь код можно будет полностью восстановить. У меня был горький опыт сохранения единого экземпляра кода одного сайта на ноут, который впоследствии сперли … С тех пор я не разлучен-с VCS и бэкап-системами типа Dropbox и храню все важные данные в интернете. Плюс удобно, что можно с легкостью получать точные копии на любую машину. Хорошо решили проблему безопасности в Aweb.ua.

И наконец, еще одна удобная штука в использовании VCS, хотя и производная от него — это возможность делать code review — обзор изменений которые сделал разработчик между версиями кода. Принципы работы code review-систем прекрасно накладываются на принципы работы VCS и поэтому они часто бывают неразлучны, когда качество кода имеет большое значение.

Распределенные VCS

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

Поэтому чтобы побороть подобные недостатки пришли распределенные системы контроля версий: Mercurial, Git, Bazaar и т.д. … Суть их проста: каждая копия проекта является одновременно и репозитарием и рабочей копией. То есть вся работа по сути выполняется локально, но существует механизм синхронизации между одинокими репозитария. При такой организации вышеупомянутые проблемы с отсутствием связи с интернетом нивелируются — вы можете делать весь спектр операций с VCS локально. Но как я уже говорил хранить данные локально — опасно, поэтому обычно в интернете открывают отдаленные репозитарии, которые служат неким хабом между людьми, которые работают с данными. То синхронизация репозитариев идет не каждый-с-каждым (хотя и такой принцип организации возможен), а все синхронизуются только с удаленным (но даже при его недоступности работа может продолжаться).

Распределенных VCS несколько. Наиболее популярные сейчас Git и Mercurial. Выбор между ними дело религиозное, но если интересно сравнить, то вот хороший анализ от Google (англ).

Работаем с Mercurial

Как я уже говорил, рабочая копия Mercurial фактически является заодно и репозиторием, но все срезы версий хранятся в каталоге. Hg из мета-информации репозитория. Вне папки собственно рабочая копия. Не удаляйте папку, вы потеряете репозиторий!

Вариантов для получения локального репозитория проекта два:

  • если он существует на другом компьютере или сервере и тогда вам надо выполнить команду clone:

1    $ Hg clone http://path/to/your/repository

она создаст копию репозитория с вказоного URL в текущем каталоге

  • если вы создаете новый проект, то нужно выполнить команду init в папке с проектом:

1  $ Hg init

затем добавить все файлы командой add:

1  $ Hg add

Внимание! У вас в каталоге могут быть файлы, которые не стоит хранить: например, «. Obj» файлы C + + или Питонивские «. рyc».

для этого в папке (на одном уровне с папкой «. hg») нужно создать файл. hgignore с содержанием типа:

1  glob:. bak

2 glob:. obj

3 glob: Debug

4  glob: Release

и так далее … Можно прописывать не только файлы, но и целые каталоги (Debug и Release в примере выше).

Далее можно работать с кодом. Если добавлялись новые файлы — не забывать выполнять команду add. Когда нужно залить изменения в репозитарий выполняем команду commit:

1 $ Hg commit

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

  1. была некоторая начальная ревизия № 1, которую для дальнейшей работы взыскали два разработчика
  2. оба что-то поправили и один был первым, кто закомитился изменения на сервер, и появилась ревизия № 2
  3. второй попытался закомитится, но сервер отказал, указав что не может залить изменения поверх версии № 1. Поэтому второй разработчик забрать себе версию № 2 из репозитория и объединить (или как часто говорят «смерджить» от англоязычного термина merge) вместе изменения по ревизии № 2 и собственные правки. Часто это происходит автоматически, но бывает, что нужно ручная правка, когда изменения касаются одинаковых фрагментов кода. Затем объединенный код можно комитить в репозиторий и да явится ревизия № 3

Таким образом, в централизованных системах есть лишь одна «главная» ревизия, а сами ревизии идут одна за другой. Вот так это выглядит схематично:

В распределенных систем нет центрального сервера, а все комиты идут локально, поэтому типичный пример работы с ними следующий:

  1. есть центральный хаб с которого два разработчика забирают единую ревизию № 1
  2. оба делают правки и локальные комиты, таким образом и у первого, и у второго на компьютере появляется по две ревизии: общая № 1 и у каждого своя № 2
  3. оба синхронизируют свои копии с общим репозитарием и в результате на общем репозитории появляется три ревизии: № 1, № 2 и № 3. Таким образом образовалось два «главных» ревизии № 2 и № 3.
  4. один из разработчиков снова синхронизирует репозиторий и у него появляется копия общего. Он может обновить локальную копию с одной из главных ревизий и продолжить работу в этой «подветке», а может объединить (смержить) изменения с № 2 и № 3 и закомитить их как ревизию № 4: таким образом граф ревизий образует ромб.

 

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

1  $ Hg pull http://path/to/your/repository

2  $ Hg push http://path/to/your/repository

Пока это вся теоретическая часть. Если вы работаете под Windows, то жизнь себе можно облегчить, если задаться TortoiseHg — графический фронт-энд для работы с Меркуриал. Плюс работу можно сделать удобной и расширить мощность системы поправив конфигурационный файл Mercurial.