Hg Init: Часть 3. Привыкаем работать в команде

<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://docs.mirocow.com/doku.php?id=hg_init:%D1%87%D0%B0%D1%81%D1%82%D1%8C_1._%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B4%D0%BB%D1%8F_%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9_subversion">«Переобучение для пользователей Subversion»</a></li> <li><a href="http://docs.mirocow.com/doku.php?id=hg_init:%D1%87%D0%B0%D1%81%D1%82%D1%8C_2._%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D1%8B_mercurial">«Основы Mercurial»</a></li> </ul><br> <br> Одно из преимуществ использования Mercurial — возможность работать командой над одним кодом. Mercurial позволяет каждому работать независимо и помогает объединять сделанные изменения.<br> <br> <h4>Часть 3. Привыкаем работать в команде</h4><br> <br> <img src="http://habrastorage.org/storage/7b7801cf/49b2fd7d/6d606de3/1c97bbd1.png" align="left"><br> При командной работе с Mercurial общепринято настраивать центральный репозиторий в дополнение к личным репозиториям, расположенным на компьютерах членов команды. Центральный репозиторий можно рассматривать как своего рода блошиный рынок, то есть, как место где встречаются и обмениваются сделанным.<br> <br> <a name="habracut"></a><br> <br> <img src="http://habrastorage.org/storage/32a5f305/c4895d33/2f30d931/4210364d.png"><br> <br> Проще всего создать центральный репозиторий при помощи встроенного в Mercurial веб-сервера. Вам нужно лишь создать репозиторий при помощи

hg init

и открыть к нему доступ при помощи

hg serve

. По умолчанию репозиторий будет доступен на 8000-ом порту.<br> <br> <img src="http://habrastorage.org/storage/1918f1bf/d865dae0/d4966f24/12e8fe35.png"><br> <br> <blockquote>

hg serve

<br> запускает веб-сервер и делает текущий репозиторий доступным в сети Интернет.<br> </blockquote><br> <br> Так как сервер запущен на компьютере <b>joel.example.com</b>, то я могу просто открыть <b>joel.example.com:8000</b> в браузере и увидеть, что сервер работает, правда репозиторий абсолютно пуст.<br> <br> <img src="http://habrastorage.org/storage/0140b8e0/896882e3/4baa6617/d1a267f3.png"><br> <br> Имея запущенный центральный веб-сервер, я могу <i>склонировать</i> центральный репозиторий <i>с сервера на мой компьютер</i> для личного пользования. Репозиторий в данный момент пуст, значит, я получу еще один пустой репозиторий в результате клонирования.<br> <br> <img src="http://habrastorage.org/storage/2c740a45/4fabec98/c98fcb7a/92f422c6.png"><br> <br> <blockquote>

hg clone

<br> делает полную копию всего репозитория.<br> </blockquote><br> <br> Теперь я создам файл <b>guac</b>, в котором запишу мой знаменитый рецепт <a href="http://ru.wikipedia.org/wiki/%D0%93%D1%83%D0%B0%D0%BA%D0%B0%D0%BC%D0%BE%D0%BB%D0%B5">гуакамоле</a>.<br> <br> <img src="http://habrastorage.org/storage/4aff84ff/486ba60c/9057e021/c0035b15.png"><br> <br> Я добавлю и закоммичу этот файл в репозиторий. Это будет первая официальная версия:<br> <br> <img src="http://habrastorage.org/storage/44d3a55b/e0d4e124/e42c1cf7/cf3b7c31.png"><br> <br> Напишу комментарий к коммиту:<br> <br> <img src="http://habrastorage.org/storage/89a503a1/b5c6d82d/6c6b4193/13248894.png"><br> <br> Я быстренько отредактирую файл, сделав одно небольшое изменение, для того, чтобы у нас было хоть немного истории изменений в репозитории.<br> <br> <img src="http://habrastorage.org/storage/deaba090/1260460f/410b04a4/5167fd72.png"><br> <br> И зафиксирую изменения:<br> <br> <img src="http://habrastorage.org/storage/233f2aa8/8318239c/90025c61/b72bd994.png"><br> <br> Обратите внимание, что когда я коммитил в этот раз, то использовал аргумент

-m

, чего раньше не делал. Это просто для того, чтобы указать комментарий к коммиту в командной строке и не использовать редактор.<br> <br> Хорошо, что у нас есть? К настоящему времени у меня есть центральный репозиторий и мой персональный клон этого репозитория. Я сделал два изменения и зафиксировал их, но эти изменения хранятся в моем клоне. В центральном репозитории их пока нет. Так что все выглядит так:<br> <br> <img src="http://habrastorage.org/storage/24badfd6/f67bd275/c3ddb80b/26b09b8b.png"><br> <br> А сейчас я воспользуюсь командой

hg push

, которая протолкнет мои изменения из локального в центральный репозиторий:<br> <br> <blockquote>

hg push

<br> проталкивает свежие изменения из текущего репозитория в центральный.<br> </blockquote><br> <br> <img src="http://habrastorage.org/storage/5a06d34f/2bc320d7/b153b069/e629a0db.png"><br> <br> Ну, отлично. Ясно видно, что так не сработает. Не хочу думать о безопасности и последствиях запуска какого-то веб-сервера с разрешением всем и каждому проталкивать в него свои тупые изменения. Потерпите немного, я собираюсь настроить сервер так, чтобы он разрешал делать всем что угодно. Нужно отредактировать файл .hg\hgrc на сервере:<br> <br> <img src="http://habrastorage.org/storage/36e5b657/454f8d10/28fb9c5f/d8f05740.png"><br> <br> Не стоит и говорить, что это небезопасно. Но если вы в защищенной локальной сети на работе, и у вас есть хороший файрвол, и вы доверяете всем в своей сети, то так вполне можно сделать. В противном случае вам стоит почитать о настройках безопасности.<br> <br> Хорошо, пора вновь запустить сервер:<br> <br> <img src="http://habrastorage.org/storage/105523b5/59e1b4bf/6342c521/267d945e.png"><br> <br> Теперь у меня должно получиться протолкнуть изменения:<br> <br> <img src="http://habrastorage.org/storage/a2b9811f/4badc381/b95e5697/f5eb54c8.png"><br> <br> Ага! Теперь все выглядит так:<br> <br> <img src="http://habrastorage.org/storage/4dbad5c0/8258e140/798f5ae3/e02b095c.png"><br> <br> Я знаю, о чем вы думаете. Вы думаете: «Господи, Джоэль, это все странно. Почему в репозиториях лежат <i>изменения</i>, а <i>не файлы</i>? Где тот файлик <b>guac</b>?».<br> <br> Ну да, странно. Но так уж работает распределенный контроль версий. Репозитории просто хранят большие стопки изменений. Представьте, что одно изменение — это как лист частично прозрачного материала. Если у вас есть пачка таких листов, и вы сложите их друг на дружку так, чтобы самое последнее изменение было сверху, а потом посмотрите на эту пачку сверху вниз, то — та-да-да-дам! — увидите текущую версию файла. Если по одному убирать листы с верха стопки, то вы будете видеть все более и более ранние версии файла.<br> <br> Воспользуемся браузером и снова заглянем в центральный репозиторий:<br> <br> <img src="http://habrastorage.org/storage/3c857027/d3fe2213/746c3e1a/bd26eb0f.png"><br> <br> Там именно то, что ожидалось.<br> <br> Теперь я позову Розу помочь мне в работе над рецептом. Роза из команды тестеров. Любой подтвердит, что она напоминает одну из тех бабулек, что можно увидеть в Вегасе, часами сидящих с отвисшей челюстью перед «одноруким бандитом» и бросающих монетку за монеткой в заветную щелку. Все отличие в том, что Роза программы тестирует. Вы можете подкинуть ей новую версию программы, и она проверит ее на 23 дистрибутивах Linux. Проверит по очереди на каждом. Не выказывая никаких эмоций, не делая лишних движений. Останавливаясь только для того, чтобы сообщить вам, что пропущена точка над i в турецкой версии Ubuntu Linux. Роза отлично тестирует, но, клянусь, иногда ведет себя как зомби.<br> <br> <img src="http://habrastorage.org/storage/371530e4/00fbd7ce/85609735/4208ce7b.png"><br> <br> Роза воспользовалась командой

hg clone

для создания своей собственной полной копии репозитория.

hg clone

принимает два аргумента: URL репозитория и имя каталога, в который вы хотите склонировать. У Розы свой каталог <b>recipes</b>.<br> <br> <img src="http://habrastorage.org/storage/3750c07a/f5b90d1b/06d55bb2/ecd4d3a6.png"><br> <br> Обратите внимание, что при выполнении

hg log

она видит всю историю. То есть Роза скачала весь репозиторий с полной историей всего, что уже произошло.<br> <br> Сейчас Роза сделает изменение и внесет его в репозиторий:<br> <br> <img src="http://habrastorage.org/storage/625ee93f/4abace04/4fa31409/85261f2d.png"><br> <br> Вот, коммитит. Обратите внимание, что она может работать даже если сервер не работает: коммит полностью выполняется на ее машине. <br> <br> <img src="http://habrastorage.org/storage/2326821c/0aa0eb4e/1b0ff6ad/985efcd6.png"><br> <br> Пока Роза делала свои изменения, я тоже кое-что сделал.<br> <br> <img src="http://habrastorage.org/storage/5e8ea447/72ead90e/263bba3f/8721f9eb.png"><br> <br> После того, как я зафиксирую свои изменения, станет видно, что в моем логе под номером два указано не то же, что у Розы.<br> <br> <img src="http://habrastorage.org/storage/2dba88e3/6da5d0aa/a3bb4bd9/7b38c1e1.png"><br> <br> Истории в наших репозиториях начали отличаться.<br> <br> <img src="http://habrastorage.org/storage/a9c1352a/9d5dc961/99774de2/5ae54129.png"><br> <br> Не переживайте, скоро увидим, как свести все эти изменения воедино для получения отменной вкусняшки с чипсами и <a href="http://ru.wikipedia.org/wiki/%D0%A5%D0%B0%D0%B1%D0%B0%D0%BD%D0%B5%D1%80%D0%BE">перчиком хабанеро</a>.<br> <br> Роза может продолжать работать без подключения к серверу, делая сколько угодно изменений. Она может фиксировать или откатывать изменения в своем репозитории. Однако настанет момент, когда она решит поделиться своими изменениями с остальными. Она может выполнить команду

hg outgoing

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

hg push

.<br> <br> <img src="http://habrastorage.org/storage/db449ef2/d6b61d93/156b0919/f19dd056.png"><br> <br> <blockquote>

hg outgoing

<br> отображает список изменений ждущих отправки в текущем репозитории.<br> </blockquote><br> <br>

hg outgoing

это просто список всех таких изменений в текущем репозитории, которых нет в центральном репозитории.<br> <br> Хорошо, вот Роза проталкивает свои изменения в центральный репозиторий.<br> <br> <img src="http://habrastorage.org/storage/7fce8e5d/56405199/c27ae4af/25722734.png"><br> <br> И теперь все выглядит так:<br> <br> <img src="http://habrastorage.org/storage/28086fde/fee793f7/af840235/a9751709.png"><br> <br> После того, как я сходил выпить четвертую чашку <a href="http://ru.wikipedia.org/wiki/%D0%9B%D0%B0%D1%82%D1%82%D0%B5">латте</a> за сегодняшний день, я тоже готов протолкнуть мое изменение про картофельные чипсы.<br> <br> <img src="http://habrastorage.org/storage/66211440/3bef48f3/e7d8fa43/4a17dfb5.png"><br> <br> ААААА!!! Ошибка! Да, кстати, видите сообщение? То, в котором написано <i>используйте ключ -f для принудительного проталкивания</i> (use push -f to force)? Это <i>ужасный</i> совет. Никогда и ни за что <b>не используйте ключ -f</b>. Вы пожалеете о том, что использовали его. Просто поверьте мне в данный момент.<br> <br> Причина, по которой у Розы получилось протолкнуть изменения, а у меня нет в том, что картофельный чипсы и гуакамоле плохо сочетаются. Шучу, шучу! Просто хотел удостовериться, что вы еще не уснули там.<br> <br> Команда завершилась с ошибкой потому, что каждый из нас сделал изменения, а значит, их нужно слить вместе, и Mercurial знает об этом.<br> <br> Первым делом я заберу все изменения из центрального репозитория, которых у меня еще нет, чтобы произвести слияние (merge).<br> <br> <img src="http://habrastorage.org/storage/cc14316f/6d00f829/c045eaff/b28a5dff.png"><br> <br> Тут какая-то тарабарщина про +1 голову (+1 heads). Это потому, что мой репозиторий, в котором раньше были аккуратно уложены три изменения, стал двухголовым монстром. На вершине репозитория опасно расположены два разных изменения. Вот как это выглядит:<br> <br> <img src="http://habrastorage.org/storage/d20fe311/841ec62a/25136b20/a75b2b3b.png"><br> <br> У меня в репозитории теперь обе версии. Вот моя:<br> <br> <img src="http://habrastorage.org/storage/7727aca4/0638daad/bddcb9a2/1cb4c06e.png"><br> <br> А вот версия Розы:<br> <br> <img src="http://habrastorage.org/storage/ccca055a/4385a92c/1b996f55/8e9755c9.png"><br> <br> И я должен слить эти версии воедино. К счастью, это просто:<br> <br> <img src="http://habrastorage.org/storage/94ed4e43/6c8c1c1c/f34767ff/9825f25a.png"><br> <br> Глядите-ка! Команда

hg merge

взяла и объединила обе мои «головы» (изменения на вершине репозитория) в одну. Так как в данном случае мы с Розой изменили разные части файла, то конфликтов при слиянии не было и все прошло без сучка без задоринки.<br> <br> <blockquote>

hg merge

<br> производит слияние (объединение) двух «голов».<br> </blockquote><br> <br> Мне по-прежнему надо сделать коммит. Это важно. Если бы слияние не удалось, то я всегда мог бы откатиться и попробовать снова. Но, так как слияние было успешным, то я сделаю коммит. После этого я смогу протолкнуть мои изменения в центральный репозиторий.<br> <br> <img src="http://habrastorage.org/storage/2372798e/f0a49c6a/2f49a1ee/75085756.png"><br> <br> Теперь в центральном репозитории то же, что в моем:<br> <br> <img src="http://habrastorage.org/storage/3301ab87/9868c9ff/9bb6c7ea/acb0e87e.png"><br> <br> Хорошо, у меня есть изменения Розы и мои собственные изменения, но у Розы пока нет моих изменений.<br> <br> Есть еще один момент, связанный с Розой, о котором я забыл рассказать. Она — доктор. Ага, доктор, который врач. Ну не чудно? Она была главным педиатром в больнице <a href="http://www.mountsinai.org/">Mt. Sinai</a> и получала, наверное, «раз в пять больше, чем этот поганый укурок платит своим тестерам». Никто наверняка не знает, почему она оставила медицину. Остальные тестеры думают, что случилось что-то трагичное. Еще у нее семья была: на ее столе картинка милого десятилетнего ребенка. Но теперь она живет одна, и мы не хотим лезть ей в душу.<br> <br> Розе нужно вытянуть (pull) свежие входящие изменения из репозитория, чтобы получить мои изменения.<br> <br> <img src="http://habrastorage.org/storage/19f31f66/0a623177/f258cc66/5667615b.png"><br> <br> Готово. Теперь, — вам может показаться это странным, — несмотря на то, что Роза втянула новые изменения в свой репозиторий, <i>эти изменения не находятся в ее рабочем каталоге</i>.<br> <br> <img src="http://habrastorage.org/storage/c8bc0274/0d8008f0/40c44b5b/b92c3101.png"><br> <br> Видите, Она по-прежнему работает с <a href="http://en.wikipedia.org/wiki/Tortilla_chip">кукурузными чипсами</a>. С кукурузными чипсами!<br> <br> У нее <i>есть</i> мои последние изменения где-то в репозитории…<br> <br> <img src="http://habrastorage.org/storage/37e67e82/67a3e142/e9022010/4fd8cfde.png"><br> <br> Просто мои изменения не в ее рабочем каталоге. Это потому, что она до сих пор изменяет второй набор изменений. Это можно увидеть, выполнив команду

hg parent

:<br> <br> <img src="http://habrastorage.org/storage/248c9d9e/b3027e43/dee45f23/6063a7e3.png"><br> <br> <blockquote>

hg parent

<br> отображает набор изменений, находящийся в рабочем каталоге.<br> </blockquote><br> <br> Mercurial добр к нам. Вытягивать изменения всегда безопасно. Все, что происходит — это получение свежих изменений, сделанных другими людьми. Мы можем начать работать с этими изменениями позже, когда нам удобно.<br> <br> Запомните, что команда

hg up

без аргументов приведет рабочий каталог к «макушке» (tip), то есть применит все изменения до самого верхнего набора изменений. В данном случае, это четвертый набор изменений:<br> <br> <img src="http://habrastorage.org/storage/06bd58a7/84eba403/73124798/54b38879.png"><br> <br> Теперь Роза видит самую свежую версию с изменениями от обоих нас.<br> <br> Когда вы работаете в команде, то рабочий процесс будет выглядеть во многом так:<br> <ol> <li>Забрать свежую версию, с которой все работают, если вы давненько этого не делали, выполнив:<br> <ul> <li>hg pull</li> <li>hg up</li> </ul><br> </li> <li>Внести изменения</li> <li>Зафиксировать изменения (локально)</li> <li>Повторить пункты 2-3 до тех пор, пока у вас не получится хороший код, который вы хотите вывалить на всех остальных</li> <li>Когда вы готовы поделиться, выполнить:<br> <ul> <li>hg pull для получения чужих изменений (если есть)</li> <li>hg merge для слияния этих изменений со своими</li> <li>тестирование! для того, чтобы удостовериться, что при слиянии ничего не попортилось</li> <li>hg commit (для фиксации результата слияния)</li> <li>hg push</li> </ul><br> </li> </ol><br> <br> <h5>Проверь себя</h5><br> <br> Вот все, что вы должны уметь делать на данный момент:<br> <ol> <li>Настроить центральный репозиторий и дать членам команды возможность делать его клоны</li> <li>Проталкивать изменения в центральный репозиторий</li> <li>Вытягивать изменения из центрального репозитория</li> <li>Делать слияние изменений от разных авторов</li> </ol><br> </html>

Продолжение здесь: Hg Init: Часть 4. Исправляем ошибки