Hg. Архитектура репозиториев. Часть 6.

<html> <div class="content">

    <img src="http://habrastorage.org/storage/eebea7f1/5482efc4/01467053/55589e0f.png" align="left">Это шестая, заключительная часть из серии <b>Hg Init: Учебное пособие по Mercurial</b> от Джоэля Спольски (<a href="http://www.joelonsoftware.com/">Joel Spolsky</a>). Предыдущие части:<br>

<ul> <li><a href="http://habrahabr.ru/blogs/development_tools/108443/">«Переобучение для пользователей Subversion»</a></li> <li><a href="http://habrahabr.ru/blogs/development_tools/108658/">«Основы Mercurial»</a></li> <li><a href="http://habrahabr.ru/blogs/development_tools/108904/">«Привыкаем работать в команде»</a></li> <li><a href="http://habrahabr.ru/blogs/development_tools/109074/">«Исправляем ошибки»</a></li> <li><a href="http://habrahabr.ru/blogs/development_tools/109203/">«Процесс слияния»</a></li> </ul><br> <br> <img src="http://habrastorage.org/storage/80a00e0e/f27de307/ccce4ca3/7532006e.png" align="left"><br> Mercurial позволяет очень гибко настроить репозитории. Плюс, так как слияния работают отлично и вы можете на них полагаться, можно иметь особые служебные репозитории в соответствии с требованиями процесса разработки в вашей команде.<br> <br> <h4>Часть 6. Архитектура репозиториев</h4><br> <br> Наш рецепт становится все лучше:<br> <br> <a name="habracut"></a><br> <br> <img src="http://habrastorage.org/storage/d68f2d22/b07c1108/357e69d3/6be4c263.png"><br> <br> Давайте приглядимся к номеру набора изменений:<br> <br> <img src="http://habrastorage.org/storage/b80f7a57/03613f2d/fb95fcea/bb2f8430.png"><br> <br> Первая часть номера, 13, короткая и удобная. Проблема в том, что… на нее нельзя полагаться!<br> <br> При независимой работе членов команды и осуществлении слияний эти короткие номера могу начать отличаться у разных членов команды:<br> <br> <img src="http://habrastorage.org/storage/a35d59b3/1ed965ee/64cf690c/4e903cb9.png"><br> <br> Так что на практике я не могу сказать: «Хорошо, давайте выпускать версию, собранную из 13 набора изменений», потому что у сотрудников может быть разное представление о том, что является 13-тым набором. Вот почему есть еще и тот безумный шестнадцатеричный номер.<br> <br> <img src="http://habrastorage.org/storage/75357326/1bf027db/eb83d6fb/73144a39.png"><br> <br> Этот шестнадцатеричный номер <i>уникален</i> во всех репозиториях и никогда не меняется.<br> <br> То есть я могу сказать людям: «Эй, сегодня релиз! 1b03ab783b17-ый набор изменений!». Согласитесь, было бы неплохо иметь возможность дать этому набору <i>имя</i>?<br> <br> Ну, у вас есть такая возможность. Такое имя называется тег (или таг, от англ. tag).<br> <br> <img src="http://habrastorage.org/storage/29f99fca/dad78d02/617c7ae2/e1015e41.png"><br> <br> Давайте теперь взглянем на лог:<br> <br> <img src="http://habrastorage.org/storage/e3f5ceba/7ef7ce12/9230375b/fdac5b68.png"><br> <br> Обратите внимание, что само добавление тега к набору изменений является набором изменений. Этот набор изменений автоматически фиксируется в репозитории (коммитится). Так что теперь каждый раз, когда я хочу сослаться на ту версию кода, что мы выпустили, я могу использовать <b>Version-1.0</b> вместо <b>1b03ab783b17</b>.<br> <br> Замдиректора спустился с 31-го этажа для того чтобы поучаствовать в офисной вечеринке по поводу выпуска новой версии и принес ящик достаточно дорогого на вид игристого вина. Стэн немного напился. Ну, не то, чтобы немного. Вообще-то, это было что-то невиданное. Стэн снял рубашку и, показывая всем свои мускулы и солидное пузо, пытался произвести впечатление на дам из отдела маркетинга. Он хвалился: «Я буду подтягиваться на лампах» (у нас в офисе используются длинные лампы дневного света). В общем, он подпрыгнул, схватился за светильник и, конечно же, оторвал его вместе с лампами и потолочной плиткой. Неудивительно, ведь светильник весом в примерно 4,5 килограмма висел на <a href="http://habrastorage.org/storage/6a621ba1/e19ec0a3/07f2e188/fee1837e.jpg">паре проволочек</a>, а вес Стэна как раз в том самом популярном диапазоне 130-135 килограммов. Повсюду было битое стекло и куски звукоизолирующей плитки. Стэн упал прямо на копчик и начал жаловаться, что засудит компанию за небезопасные условия труда.<br> <br> Остальные вернулись на рабочие места для работы над Guac 2.0.<br> <br> <img src="http://habrastorage.org/storage/c9f4e36c/0637f3bf/d472f6a8/c1d4fdea.png"><br> <br> Коммит:<br> <br> <img src="http://habrastorage.org/storage/0031b86c/94b2ba74/1baa1291/493613a4.png"><br> <br> Не стоит и говорить, что этот рецепт пока сомнителен. Его не тестировали, к примеру. И тут звонит клиент.<br> <br> «Слишком солёно получается!», скулит клиент. И нет, он не желает подождать выхода версии 2.0 с исправлением ошибки.<br> <br> К счастью, у нас есть тот тег. Я могу использовать

hg up

для перехода к любой версии в репозитории.<br> <br> <img src="http://habrastorage.org/storage/633fedc2/cc2c66c1/cb5d3c8f/42cbc002.png"><br> <br> Теперь я могу исправить эту тупую проблему с солью:<br> <br> <img src="http://habrastorage.org/storage/6a67553e/093ccf44/d290f910/6956c6f1.png"><br> <br> Затем:<br> <br> <img src="http://habrastorage.org/storage/efe56ec9/58727a58/94a0e492/e56d5553.png"><br> <br> Mercurial напоминает мне, что мои действия создали новую голову. Теперь в репозитории две головы: версия 2.0, над которой я недавно работал, и версия, которую я только что закоммитил.<br> <br> <img src="http://habrastorage.org/storage/461735ea/624be09a/a8b26521/af885f2f.png"><br> <br> В данный момент я могу отдать версию с последними изменениями клиенту, пометить ее как 1.1, и продолжить работать с версией 2.0.<br> <br> <img src="http://habrastorage.org/storage/71bc196d/41345306/1ef4d16e/9ab05419.png"><br> <br> Но есть одна проблема… исправления про соль отсутствуют в версии 2.0. Как мне это исправить?<br> <br> <img src="http://habrastorage.org/storage/45277523/d4534deb/e6e778b4/f3665feb.png"><br> <br> <img src="http://habrastorage.org/storage/72edbdf4/50bd8cdd/e08640a9/32196428.png"><br> <br> Ну вот. Я должен сделать слияние тегов. Это известный баг в Mercurial. Проблема в том, что теги в Mercurial — это просто файл с именем .hgtags, для которого тоже ведется контроль версий. Поэтому время от времени вам нужно вручную делать слияние разных версий файла .hgtags. В такой ситуации ваши действия просты… нужно всегда сохранять ОБЕ версии каждой строки в файле.<br> <br> <img src="http://habrastorage.org/storage/1aa9272a/8bcae15c/b09cb4ec/5242aae8.png"><br> <br> Описанный выше простой способ перейти к старой, помеченной версии годится, если вам нужно сделать лишь одно маленькое незапланированное изменение в выпущенном коде. Но правда в том, что в большинстве программных проектов такие ситуации возникают постоянно, а у Mercurial есть более надежный способ разобраться с ними.<br> <br> Так что я сейчас отменю все изменения, сделанные после 1.0, верну репозиторий в состояние, которое у него было в момент выпуска 1.0, и затем смогу показать вам модный надежный способ исправлять баги существующих клиентов и параллельно работать над новой версией.<br> <br> <img src="http://habrastorage.org/storage/920e88ad/36225520/5db9dd52/ddf8aa7a.png"><br> <br> Идея в том, что вместо работы с одним репозиторием мы заведем два репозитория. Один репозиторий назовем <b>stable</b>, а второй — <b>dev</b>.<br> <br> В репозитории <b>stable</b> хранится последняя мажорная версия кода, отправленная клиентам. Каждый раз, когда вам нужно срочно исправить баг, вы делаете это в <b>stable</b>. В нашем примере, все патчи для версии 1.0 попадут в <b>stable</b>.<br> <br> Репозиторий <b>dev</b> — это то место, где ведется разработка следующей мажорной версии, то есть версии 2.0.<br> <br> Как только вышла версия 1.0, я клонирую <b>stable</b> в <b>dev</b>:<br> <br> <img src="http://habrastorage.org/storage/874eef22/a1545d93/a0232e75/95342a96.png"><br> <br> Теперь у меня два идентичных репозитория:<br> <br> <img src="http://habrastorage.org/storage/6a6b8010/f84d4b0a/78f25f9a/49c5c0bc.png"><br> <br> Так как история в обоих репозиториях одинакова до 14-го набора изменений включительно, то Mercurial воспользуется "<a href="http://ru.wikipedia.org/wiki/%D0%96%D1%91%D1%81%D1%82%D0%BA%D0%B0%D1%8F_%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B0">жёсткими ссылками</a>" вместо того, чтобы делать две копии на диске. Поэтому операция

hg clone

выполняется быстро и дешево, а значит, вы можете без колебаний делать много-много клонов репозитория.<br> <br> Теперь начнем работать над guac в репозитории <b>dev</b>:<br> <br> <img src="http://habrastorage.org/storage/905ffd18/8d990fe0/40ba5e86/0f957768.png"><br> <br> И исправим ту проблему с солью в репозитории <b>stable</b>:<br> <br> <img src="http://habrastorage.org/storage/93b7491a/01cd83a3/2f852c5c/aea3d2a8.png"><br> <br> Я помечу эту версию и выпущу ее как 1.1:<br> <br> <img src="http://habrastorage.org/storage/d5ca3f6d/5a1321e9/abf90da0/35c32879.png"><br> <br> Теперь, время от времени, нам нужно втягивать изменения из <b>stable</b> в <b>dev</b>:<br> <br> <img src="http://habrastorage.org/storage/b8a8ffd4/dc5c701b/3b95d143/21255c0d.png"><br> <br> Вот что мы только что сделали:<br> <br> <img src="http://habrastorage.org/storage/53bf82a1/b62b1a9f/ee8752b7/398d919f.png"><br> <br> И если вы можете понять, что нарисовано на <i>этой</i> безумной картинке, то с пониманием Mercurial у вас больше проблем не будет. Суть в том, что в репозиторий <b>stable</b> попадают только исправления ошибок, а в репозитории <b>dev</b> хранится новый код и проводятся слияния с исправлениями ошибок.<br> <br> Есть и другие применения нескольким репозиториям.<br> <br> <ul> <li> Вы можете настроить командные репозитории, в которых несколько человек вместе работают над каким-то новым функционалом. Когда они закончат и все сделанное будет работать правильно, вы протолкнете изменения из командного репозитория в главный репозиторий, и все увидят эти изменения.<br> </li> <li> Вы можете настроить репозиторий для тестеров. Вместо того чтобы сразу проталкивать изменения в главный репозиторий, вы будете проталкивать изменения в репозиторий тестеров. Тестеры проверят изменения и когда (и если) изменения будут одобрены, вы сможете протолкнуть изменения из репозитория тестеров в главный репозиторий. При таком подходе главный репозиторий всегда будет содержать протестированный код.<br> </li> <li> Так как у каждого разработчика свой репозиторий, то вы можете вытягивать на пробу экспериментальные изменения из репозитория товарища, не влияя на работу остальной команды.<br> </li> </ul><br> <br> В больших сложно устроенных организациях вы можете комбинировать эти техники и настраивать цепочки репозиториев, вытягивающих изменения друг из друга. По мере того, как какой-то функционал проходит этапы тестирования и интеграции, он втягивается в репозитории по цепочке до тех пор, пока, наконец, не окажется в главном репозитории, хранящем код, который получают клиенты:<br> <br> <img src="http://habrastorage.org/storage/aa0f38ff/e5a593c6/0470c7bd/89c7c3d4.png"><br> <br> <h5>Проверь себя</h5><br> <br> Вот то, что вы должны уметь делать после прочтения данной части:<br> <ol> <li>Помечать старые версии и возвращаться к ним.</li> <li>Организовывать работу команды с двумя репозиториями (stable и dev).</li> </ol><br> <br> Что ж, так получилось, что мы дошли до конца пособия. Я даже <i>близко не подобрался</i> к тому, чтобы описать все возможности Mercurial, но есть достаточное число материалов для углубленного изучения. Есть <a href="http://hgbook.red-bean.com/">книга</a>, которая описывает все крайне подробно. И если у вас есть какие-либо вопросы, то я приглашаю вас на сайт <a href="http://kiln.stackexchange.com/">Kiln Knowledge Exchange</a> (это как <a href="http://stackoverflow.com/">StackOverflow</a>, только для Kiln, и вопросы про Mercurial более чем приветствуются на этом сайте).<br> </html>