0,0
рейтинг
26 ноября 2010 в 21:22

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

Это третья часть из серии Hg Init: Учебное пособие по Mercurial от Джоэля Спольски (Joel Spolsky). Предыдущие части:


Одно из преимуществ использования Mercurial — возможность работать командой над одним кодом. Mercurial позволяет каждому работать независимо и помогает объединять сделанные изменения.

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




При командной работе с Mercurial общепринято настраивать центральный репозиторий в дополнение к личным репозиториям, расположенным на компьютерах членов команды. Центральный репозиторий можно рассматривать как своего рода блошиный рынок, то есть, как место где встречаются и обмениваются сделанным.





Проще всего создать центральный репозиторий при помощи встроенного в Mercurial веб-сервера. Вам нужно лишь создать репозиторий при помощи hg init и открыть к нему доступ при помощи hg serve. По умолчанию репозиторий будет доступен на 8000-ом порту.



hg serve
запускает веб-сервер и делает текущий репозиторий доступным в сети Интернет.


Так как сервер запущен на компьютере joel.example.com, то я могу просто открыть joel.example.com:8000 в браузере и увидеть, что сервер работает, правда репозиторий абсолютно пуст.



Имея запущенный центральный веб-сервер, я могу склонировать центральный репозиторий с сервера на мой компьютер для личного пользования. Репозиторий в данный момент пуст, значит, я получу еще один пустой репозиторий в результате клонирования.



hg clone
делает полную копию всего репозитория.


Теперь я создам файл guac, в котором запишу мой знаменитый рецепт гуакамоле.



Я добавлю и закоммичу этот файл в репозиторий. Это будет первая официальная версия:



Напишу комментарий к коммиту:



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



И зафиксирую изменения:



Обратите внимание, что когда я коммитил в этот раз, то использовал аргумент -m, чего раньше не делал. Это просто для того, чтобы указать комментарий к коммиту в командной строке и не использовать редактор.

Хорошо, что у нас есть? К настоящему времени у меня есть центральный репозиторий и мой персональный клон этого репозитория. Я сделал два изменения и зафиксировал их, но эти изменения хранятся в моем клоне. В центральном репозитории их пока нет. Так что все выглядит так:



А сейчас я воспользуюсь командой hg push, которая протолкнет мои изменения из локального в центральный репозиторий:

hg push
проталкивает свежие изменения из текущего репозитория в центральный.




Ну, отлично. Ясно видно, что так не сработает. Не хочу думать о безопасности и последствиях запуска какого-то веб-сервера с разрешением всем и каждому проталкивать в него свои тупые изменения. Потерпите немного, я собираюсь настроить сервер так, чтобы он разрешал делать всем что угодно. Нужно отредактировать файл .hg\hgrc на сервере:



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

Хорошо, пора вновь запустить сервер:



Теперь у меня должно получиться протолкнуть изменения:



Ага! Теперь все выглядит так:



Я знаю, о чем вы думаете. Вы думаете: «Господи, Джоэль, это все странно. Почему в репозиториях лежат изменения, а не файлы? Где тот файлик guac?».

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

Воспользуемся браузером и снова заглянем в центральный репозиторий:



Там именно то, что ожидалось.

Теперь я позову Розу помочь мне в работе над рецептом. Роза из команды тестеров. Любой подтвердит, что она напоминает одну из тех бабулек, что можно увидеть в Вегасе, часами сидящих с отвисшей челюстью перед «одноруким бандитом» и бросающих монетку за монеткой в заветную щелку. Все отличие в том, что Роза программы тестирует. Вы можете подкинуть ей новую версию программы, и она проверит ее на 23 дистрибутивах Linux. Проверит по очереди на каждом. Не выказывая никаких эмоций, не делая лишних движений. Останавливаясь только для того, чтобы сообщить вам, что пропущена точка над i в турецкой версии Ubuntu Linux. Роза отлично тестирует, но, клянусь, иногда ведет себя как зомби.



Роза воспользовалась командой hg clone для создания своей собственной полной копии репозитория. hg clone принимает два аргумента: URL репозитория и имя каталога, в который вы хотите склонировать. У Розы свой каталог recipes.



Обратите внимание, что при выполнении hg log она видит всю историю. То есть Роза скачала весь репозиторий с полной историей всего, что уже произошло.

Сейчас Роза сделает изменение и внесет его в репозиторий:



Вот, коммитит. Обратите внимание, что она может работать даже если сервер не работает: коммит полностью выполняется на ее машине.



Пока Роза делала свои изменения, я тоже кое-что сделал.



После того, как я зафиксирую свои изменения, станет видно, что в моем логе под номером два указано не то же, что у Розы.



Истории в наших репозиториях начали отличаться.



Не переживайте, скоро увидим, как свести все эти изменения воедино для получения отменной вкусняшки с чипсами и перчиком хабанеро.

Роза может продолжать работать без подключения к серверу, делая сколько угодно изменений. Она может фиксировать или откатывать изменения в своем репозитории. Однако настанет момент, когда она решит поделиться своими изменениями с остальными. Она может выполнить команду hg outgoing и увидеть список изменений, ожидающих отправки в центральный репозиторий. Это те изменения, которые будут отправлены при выполнении hg push.



hg outgoing
отображает список изменений ждущих отправки в текущем репозитории.


hg outgoing это просто список всех таких изменений в текущем репозитории, которых нет в центральном репозитории.

Хорошо, вот Роза проталкивает свои изменения в центральный репозиторий.



И теперь все выглядит так:



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



ААААА!!! Ошибка! Да, кстати, видите сообщение? То, в котором написано используйте ключ -f для принудительного проталкивания (use push -f to force)? Это ужасный совет. Никогда и ни за что не используйте ключ -f. Вы пожалеете о том, что использовали его. Просто поверьте мне в данный момент.

Причина, по которой у Розы получилось протолкнуть изменения, а у меня нет в том, что картофельный чипсы и гуакамоле плохо сочетаются. Шучу, шучу! Просто хотел удостовериться, что вы еще не уснули там.

Команда завершилась с ошибкой потому, что каждый из нас сделал изменения, а значит, их нужно слить вместе, и Mercurial знает об этом.

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



Тут какая-то тарабарщина про +1 голову (+1 heads). Это потому, что мой репозиторий, в котором раньше были аккуратно уложены три изменения, стал двухголовым монстром. На вершине репозитория опасно расположены два разных изменения. Вот как это выглядит:



У меня в репозитории теперь обе версии. Вот моя:



А вот версия Розы:



И я должен слить эти версии воедино. К счастью, это просто:



Глядите-ка! Команда hg merge взяла и объединила обе мои «головы» (изменения на вершине репозитория) в одну. Так как в данном случае мы с Розой изменили разные части файла, то конфликтов при слиянии не было и все прошло без сучка без задоринки.

hg merge
производит слияние (объединение) двух «голов».


Мне по-прежнему надо сделать коммит. Это важно. Если бы слияние не удалось, то я всегда мог бы откатиться и попробовать снова. Но, так как слияние было успешным, то я сделаю коммит. После этого я смогу протолкнуть мои изменения в центральный репозиторий.



Теперь в центральном репозитории то же, что в моем:



Хорошо, у меня есть изменения Розы и мои собственные изменения, но у Розы пока нет моих изменений.

Есть еще один момент, связанный с Розой, о котором я забыл рассказать. Она — доктор. Ага, доктор, который врач. Ну не чудно? Она была главным педиатром в больнице Mt. Sinai и получала, наверное, «раз в пять больше, чем этот поганый укурок платит своим тестерам». Никто наверняка не знает, почему она оставила медицину. Остальные тестеры думают, что случилось что-то трагичное. Еще у нее семья была: на ее столе картинка милого десятилетнего ребенка. Но теперь она живет одна, и мы не хотим лезть ей в душу.

Розе нужно вытянуть (pull) свежие входящие изменения из репозитория, чтобы получить мои изменения.



Готово. Теперь, — вам может показаться это странным, — несмотря на то, что Роза втянула новые изменения в свой репозиторий, эти изменения не находятся в ее рабочем каталоге.



Видите, Она по-прежнему работает с кукурузными чипсами. С кукурузными чипсами!

У нее есть мои последние изменения где-то в репозитории…



Просто мои изменения не в ее рабочем каталоге. Это потому, что она до сих пор изменяет второй набор изменений. Это можно увидеть, выполнив команду hg parent:



hg parent
отображает набор изменений, находящийся в рабочем каталоге.


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

Запомните, что команда hg up без аргументов приведет рабочий каталог к «макушке» (tip), то есть применит все изменения до самого верхнего набора изменений. В данном случае, это четвертый набор изменений:



Теперь Роза видит самую свежую версию с изменениями от обоих нас.

Когда вы работаете в команде, то рабочий процесс будет выглядеть во многом так:
  1. Забрать свежую версию, с которой все работают, если вы давненько этого не делали, выполнив:
    • hg pull
    • hg up

  2. Внести изменения
  3. Зафиксировать изменения (локально)
  4. Повторить пункты 2-3 до тех пор, пока у вас не получится хороший код, который вы хотите вывалить на всех остальных
  5. Когда вы готовы поделиться, выполнить:
    • hg pull для получения чужих изменений (если есть)
    • hg merge для слияния этих изменений со своими
    • тестирование! для того, чтобы удостовериться, что при слиянии ничего не попортилось
    • hg commit (для фиксации результата слияния)
    • hg push



Проверь себя


Вот все, что вы должны уметь делать на данный момент:
  1. Настроить центральный репозиторий и дать членам команды возможность делать его клоны
  2. Проталкивать изменения в центральный репозиторий
  3. Вытягивать изменения из центрального репозитория
  4. Делать слияние изменений от разных авторов


Продолжение здесь:
Hg Init: Часть 4. Исправляем ошибки
Перевод: Joel Spolsky
Сергей Бобровский @Bobrovsky
карма
145,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

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

  • 0
    Давно еще перевел все проекты с svn на HG на сервис bitbucket. Очень доволен. Сама идеология mercurial очень доставляет.
  • 0
    Такое ощущение, что в этой части несколько развенчан миф об удобстве hg serve по сравнению с поднятием сервера для Git.
    А вот отдельная команда hg outgoing Меркуриалу в плюс. Посмотрим, что будет дальше :-)
    • 0
      Каким же образом развенчан?
      • 0
        Тем, что на пальцах объёснить поднятие сервера с авторизацией не получилось :-) А для внутренней сети можно и общую папку на сервере сделать.
        • +1
          Рискну предположить, что искаробочный сервер для этого и не предназначен.
          Если точнее, авторизацию ни одна из VCS (кроме грядущей veracity и вроде как fossil) не умеет. Следовательно, встроенная вебморда тоже не обязана авторизовывать юзеров.
  • +2
    классные статьи, Джоэль молодец, переводчик тоже
    поставил ради интереса, довольно удобно
  • +3
    Хорошо что переводы так часто выходят. Главное — не бросайте на пол пути.
    • +2
      В планах примерно такой же темп. Осталось всего три части, опять же.
  • 0
    Спасибо.

    Вопрос: hg serve достаточно надежён, чтобы жить в «диком интернете»? И как у него с потреблением ресурсов при достаточно долгой работе (месяцами, хотя и с небольшим числом push/poll — 2-3 раза в день) без перезапусков?
    • +1
      У него нет аутентификации, тянуть могут все (pull), заливать (push) — или никто или все. Для постояннодействующих репозиториев надо юзать cgi-шку, которая идет в поставке (hgweb).
  • 0
    В статье всё слишком просто. Даже не знаю кому понадобится такой hg serve.
    1. Нет нормальной аутентификации.
    2. Серв запускается для одного репозитория. Т.е. для одного проекта.

    Начал читать маны по поднятию нормального сервера. Вспомнил мучения с mod_dav и mod_dav_fs. Вспомнил как потом радовался выходу коробочного решения VisualSVN Server. Поставил и всё заработало без mod_dav. А теперь чувствую себя так, словно меня откатили назад в прошлое.

    TortoiseHg пока тоже слишком далеко до TortoiseSVN. Даже пароль от репо не может запомнить. Приходится каждые 5 минут его набирать при каждом pull/push.

    P.S. Всё равно отличный цикл статей. Без них я бы даже не стал возиться с hg. Надеюсь, mercurial разовьётся до уровня SVN, что бы его было приятно использовать.
    • 0
      mercurial.selenic.com/wiki/HgWebDirStepByStep

      hgwebdir.cgi работает cgi-шкой под апачем без особых танцев с бубном

      Мои настройки апача:

      ServerName ДОМЕН
      Redirect permanent / ДОМЕН/

      ServerName ДОМЕН
      ScriptAlias /mysqldump /var/hg/mysqldump.cgi
      ScriptAliasMatch ^(.*) /var/hg/hgwebdir.cgi$1

      CustomLog /var/hg/log/access.log combined
      ErrorLog /var/hg/log/error.log

      SSLEngine On
      SSLCertificateFile /etc/apache2/ssl/apache.pem

      AuthType Basic
      AuthName «Mercurial Server»
      AuthUserFile /var/hg/.htpasswd
      require valid-user


      • 0
        опять как-то отправилось само… первые две строчки для редиректа с http на https, съелись теги [VirtualHost] и [Location ~ "/.*"] (перед AuthType)
        • +1
          Да. После того как один раз разберёшься, всё кажется совершенно примитивным и очевидным.
    • 0
      TortoiseHG может запомнить пароль (картинка кликабельна), просто по умолчанию этого не делает:



      Кстати, делать каждые 5 минут pull/push вроде не совсем в духе Mercurial.
      • 0
        Да действительно всё легко работает.
        Ну всё, уговорили. Пересаживаюсь на меркуриал
        хотя галки «запомнить пароль» ему всё же не хватает.
        • –2
          А мне гораздо больше bazaar нравится — рекомендую посмотреть
      • +1
        Ой-ой.
        Весьма не рекомендую запоминать пароли именно так.
        После этого ваш пароль в открытом виде хранится на диске в репозитории.
        Правильнее будет в расширениях поставить птичку напротив mercurial_keyring, а на приведенной выше форме указать только имя пользователя.
        Тогда тому, кто захочет заполучить ваш пароль прийдется сначала взломать keyring :)
        • +1
          Кстати, интересно, поддерживает ли mercurial_keyring винды. Там же вроде как тоже есть какое-то хранилище юзерских секретов (которым практически никто не пользуется, да)?
          • 0
            Как он устроен внутри — не разбирался. Но под виндой все работает на ура.
            • 0
              под виндой все работает на ура
              ну и отлично [х]
    • +1
      hg serve подходит быстрого обмена внутри локалки и только, о чём явно написано в документации. Репозитории типа Bitbucket его, разумеется, не используют — там CGI/WSGI/mod_python. Читайте мануал на сайте Mercurial, всё довольно просто. Можно кстати ещё запустить hg serve с Nginx в режиме прокси и использовать обычную HTTP-аутентификацию.

      TortoiseHG прекрасно запоминает пароли, кстати.

      mercurial.selenic.com/wiki/PublishingRepositories

      P.S. mercurial давно развился до уровня SVN, а во многом и превзошёл. И мануалы надо иногда читать.
    • +1
      я тут попробовал все тортойсы. пользоваться можно только свн-овским и гит-овским. остальные — кривые поделки.
  • +1
    Вопрос к людям с опытом использования меркуриала. Немного смутила фраза
    > Никогда и ни за что не используйте ключ -f.
    Если я создам отдельную ветку (named branch), то тоже нужен будет ключ -f, чтобы протолкнуть её в основной репозиторий. Что ужасного в таком действии? Как обойтись без этого, если ветка ведется дольше пары-тройки дней? Если ветка ведется более чем одним человеком?
  • +2
    Сделал у себя вот так Setting up a Mercurial server under IIS7 on Windows Server 2008 R2 на Win7
    • 0
      Спасибо, очень познавательно.
      • 0
        Забыл упомянуть, чтобы все заработало без проблем необходим Python 2.6.6
      • 0
        Вот тут можешь посмотреть как настроить сервер для винды под Apache. Это я для себя делал, но может пригодится
  • 0
    Спасибо. Понятные примеры в объяснениях воодушевляют меня исследовать hg дальше!
  • 0
    Жаль, из статьи не видно, что в современных GUI осваивать Mercurial еще проще.

    А начинание хорошее у вас.
  • 0
    Что меня сильно смущает (если говорить деликатно) в этих ваших распределенных системах контроля версий, так это то, что каждой из них обязательно надо изобрести свою собственную терминологию, по возможности отличающуюся от централизованных систем, чтобы, не дай боже, не спутали. В результате при чтении статей по Git и Hg вместо «Ага! Вот они те же команды, всё ясно» приходится медитировать на описание процессов и проводить параллели.
    • 0
      В первой части цикла этот момент всколзь затрагивается. Дело в том, что распределенные системы работают не так, как централизованные, потому и терминология другая. Не для всех действий в одной системе есть точное соответствие в другой системе.
    • 0
      не надо проводить параллели, это только вредит пониманию. если hg ещё более-менее смахивает на svn, то git — это вообще другая планета.
  • +1
    а есть скв кроме свн, где каждая директория может использоваться как отдельная репа? и, например, можно одну директорию примержить к другой с сохранением истории.
    • 0
      mercurial.selenic.com/wiki/Subrepository?action=show&redirect=subrepos
      По моему это то что вы хотите.
      • 0
        не, это совсем не то. создавать отдельную репу на каждый модуль — это слишком геморройно. в гите я выкрутился так, что каждый модуль в отдельной ветке одной репы. но как-то это криво.
        • 0
          криво, да. в git же есть submodules.
          • 0
            создай пару десятков реп на гитхабе, а я посмотрю как ты в них будешь копаться.

            и частичный чекаут — тоже не то. всё на что он годен — возможность не выкачивать всю репу. при изменении структуры директорий все дружно сосут.
            • 0
              частичный чекаут — тоже не то
              ну посмотрите Bazaar — вроде как там частичный чекаут реализован правильно.
    • 0
      Это называется, кажется, partial checkout.
  • 0
    В статье не описано преимущество Hg. SVN в данном случае удобнее, потому как на один шаг меньше.
    • 0
      Отличие Hg от SVN и его преимущества описаны в первой статье из цикла habr.ru/post/108443/

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.