Основы Mercurial. Часть 2.

<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>). Возможно, вы захотите прочитать и первую часть [[hg_init:часть_1._переобучение_для_пользователей_subversion|]].<br>

<br> Даже если вы работаете в одиночку, то вам стоит использовать Mercurial. Так вы сможете получить все прелести контроля версий. Эта часть покажет насколько просто добавить каталог в Mercurial, чтобы с легкостью отслеживать предыдущие версии.<br> <br> <h4>Часть 2. Основы Mercurial</h4><br> <br> <img src="http://habrastorage.org/storage/a2dc0ced/1ebe349c/adafba84/cf7127dd.png" align="left">Mercurial — это <i>система контроля версий</i>. Разработчики используют ее для администрирования исходного кода. У нее два основных назначения:<br> <ol> <li>Она хранит все предыдущие версии каждого файла</li> <li>Она может объединить разные версии вашего кода, то есть сотрудники могут независимо работать над кодом и затем объединять свои изменения</li> </ol><br> <br> <a name="habracut"></a><br> <br> Без Mercurial вы могли бы попытаться сохранить предыдущие версии, просто создавая много копий каталога с кодом:<br> <br> <img src="http://habrastorage.org/storage/c204c8c2/8cbde270/f057de30/d4010d6d.png"><br> <br> Это муторно, требует много места на диске и создает путаницу. Лучше использовать систему контроля версий.<br> <br> Большинство людей работают с Mercurial через интерфейс командной строки. Так можно работать в Windows, Unix, и Mac. Команда для Mercurial — это

hg

:<br> <br> <img src="http://habrastorage.org/storage/d1a7ded2/0e111d9f/ff11aa6a/06d714d8.png"><br> <br> Если выполнить

hg

без параметров, то вы получите список наиболее часто используемых команд. Вы можете также попробовать выполнить

hg help

для получения полного списка команд.<br> <br> Для того чтобы воспользоваться преимуществами контроля версий, вам нужен <i>репозиторий</i>. Репозиторий хранит все предыдущие версии всех ваших файлов. На самом деле, для экономии места на диске, все предыдущие версии не будут храниться — будет храниться только компактный список изменений.<br> <br> В старые времена заиметь репозиторий было большим делом. Вам было необходимо иметь центральный сервер и нужно было установить на него программное обеспечение. Mercurial — <i>распределенная</i> система, так что вы можете использовать ее без модного центрального сервера. Вы можете пользоваться Mercurial, используя один только свой компьютер. А заполучить репозиторий супер просто: вы просто идете в каталог с вашим кодом…<br> <br> <img src="http://habrastorage.org/storage/df024955/0a7c68ad/4d8a48b9/032e8174.png"><br> <br> … и выполняете команду

hg init

:<br> <br> <img src="http://habrastorage.org/storage/6d17bad7/1023e58b/cbf778f1/de0f8775.png"><br> <br> <blockquote>

hg init

<br> создает репозиторий.<br> </blockquote><br> <br> Минуточку, а разве что-то произошло? Выглядит так, словно ничего не поменялось. Нет, если вы присмотритесь получше, то увидите, что появился новый каталог

.hg

:<br> <br> <img src="http://habrastorage.org/storage/8f6b4eec/b4aa6daf/c822a60f/ea555032.png"><br> <br> Это и есть репозиторий! Это каталог со всем, что нужно Mercurial для работы. Настройки, предыдущие версии файлов, теги, лишняя пара носков на случай дождя, и прочее. <i>Не лазьте туда.</i> Вам почти всегда не стоит возиться с этим каталогом самостоятельно.<br> <br> Ну хорошо, раз у нас теперь есть свежеиспеченный репозиторий, то мы захотим добавить в него все исходные файлы. Это тоже просто: нужно лишь выполнить

hg add

.<br> <br> <img src="http://habrastorage.org/storage/0deb8fc5/d3543931/6114cd9a/f166b892.png"><br> <br> <blockquote>

hg add

<br> помечает файлы как запланированные для добавления в репозиторий. Файлы на самом деле не будут добавлены до тех пор, пока вы не зафиксируете изменения.<br> </blockquote><br> <br> Остался еще один шаг… вам нужно <i>зафиксировать ваши изменения</i>. Какие изменения? Факт добавления всех этих файлов.<br> <br> Почему вы вынуждены фиксировать изменения? При работе с Mercurial фиксирование изменений означает: «Эй, вот как файлы сейчас выглядят, так их и запомни, пожалуйста». Это как создание копии всего каталога… каждый раз, когда у вас есть что-то измененное, и оно вам типа нравится, то вы фиксируете изменения.<br> <br> <blockquote>

hg commit

<br> сохраняет текущее состояние всех файлов в репозиторий.<br> </blockquote><br> <br> <img src="http://habrastorage.org/storage/1b0b9bd3/265a2c06/84473f38/64028691.png"><br> <br> Mercurial запустит редактор для того, чтобы вы могли напечатать комментарий к изменениям. Вам нужно просто написать что-нибудь, что напомнит вам о сделанных изменениях.<br> <br> <img src="http://habrastorage.org/storage/d47213d9/eab868b9/894d01ae/68290364.png"><br> <br> После сохранения и выхода из редактора ваши изменения будут зафиксированы.<br> <br> Вы можете выполнить

hg log

для просмотра истории изменений. Это как блог для вашего репозитория:<br> <br> <img src="http://habrastorage.org/storage/63c37c68/7c4b9074/79365c85/9158e135.png"><br> <br> <blockquote>

hg log

<br> отображает историю изменений, зафиксированных в репозитории.<br> </blockquote><br> <br> Давайте изменим файл и посмотрим, что получится.<br> <br> <img src="http://habrastorage.org/storage/a4976b63/e1120125/f2d75af8/175793cf.png"><br> <br> Так как мы сделали изменение, то можем его зафиксировать при помощи

hg commit

:<br> <br> <img src="http://habrastorage.org/storage/1b0b9bd3/265a2c06/84473f38/64028691.png"><br> <br> Обратите внимание, что Mercurial догадался, что только один файл, a.txt, изменен:<br> <br> <img src="http://habrastorage.org/storage/7e7e4f7c/44a2a982/429514a6/ea1f8d40.png"><br> <br> А теперь, после того как я закоммитил (зафиксировал изменения), давайте посмотрим на историю:<br> <br> <img src="http://habrastorage.org/storage/30655b31/b8a4769b/cabb993c/cd4bad09.png"><br> <br> Как любой нынешний блоггер, Mercurial помещает самое новое в начало.<br> <br> Я собираюсь сделать еще одно изменение, просто чтобы потешить себя.<br> <br> <img src="http://habrastorage.org/storage/ce916884/653f2957/8d61c6eb/daeab3db.png"><br> <br> Коммичу (фиксирую изменения):<br> <br> <img src="http://habrastorage.org/storage/1b0b9bd3/265a2c06/84473f38/64028691.png"><br> <br> Мое сообщение к коммиту:<br> <br> <img src="http://habrastorage.org/storage/64909d63/4d121c11/5243ddb9/f16bd56c.png"><br> <br> А что у нас теперь в истории?<br> <br> <img src="http://habrastorage.org/storage/f8759acb/815f0236/1614fff7/7b5449b8.png"><br> <br> Хорошо, это было весело. Я сделал несколько изменений и каждый раз, сделав значимое изменение, я фиксировал его в репозитории.<br> <br> Я знаю, вы сейчас думаете: «ДЖОЭЛЬ, ВСЕ ЭТО ВЫГЛЯДИТ ПУСТОЙ ТРАТОЙ ВРЕМЕНИ». К чему вся эта катавасия с коммитами?<br> <br> Терпение, мой юный друг. Ты вот-вот узнаешь, как извлечь выгоду из всего этого.<br> <br> Для начала: скажем, вы сделали большую ошибку в процессе редактирования.<br> <br> <img src="http://habrastorage.org/storage/1e32f444/b934daf5/5dab5b35/d90f3dec.png"><br> <br> А затем, боже ж мой, в дополнение ко всему вы удалили пару очень важных файлов.<br> <br> <img src="http://habrastorage.org/storage/74f57309/93aecdca/9cb11413/afb87796.png"><br> <br> Во времена, когда не было Mercurial, это все могло бы стать неплохим поводом для похода к системному администратору. Там, со слезами на глазах, вы бы задали ему пронзительно грустный вопрос: «Почему система резервного копирования „временно“ не работает все последние восемь месяцев».<br> <br> Системный администратор, которого все зовут <a href="http://ru.wikipedia.org/wiki/%D0%A2%D0%B0%D0%BA%D0%BE">Тако</a>, слишком скромен и не обедает с остальной командой. В тех редких случаях, когда он не сидит в своем кресле на колесиках, можно увидеть треугольное пятно цвета <a href="http://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BB%D1%8C%D1%81%D0%B0_(%D1%81%D0%BE%D1%83%D1%81)">сальсы</a> там, где падали, пролетев между ног, капли от его мексиканских закусок. Эти капли гарантируют, что никто не возьмет его кресло, хотя это <a href="http://hermanmiller.com/Products/Aeron-Chairs">одно из превосходных кресел от Herman Miller</a>, купленных учредителями компании для себя любимых, а не обычное бюджетное офисное нечто, из-за которого у всех болят спины.<br> <br> В любом случае, резервной копии нет, ага.<br> <br> Благодаря Mercurial, если вам не нравится то, что вы сделали, вы можете выполнить удобную команду

hg revert

, которая немедленно вернет ваш каталог к виду, в котором он был в момент последнего коммита.<br> <br> <img src="http://habrastorage.org/storage/faad2087/64fce902/eb83246d/28a37ffa.png"><br> <br> <blockquote>

hg revert

<br> возвращает измененные файлы к зафиксированному в репозитории виду.<br> </blockquote><br> <br> Я использовал аргумент

--all

, потому что хотел вернуть <i>все</i> файлы к прежнему состоянию.<br> <br> Таким образом, когда вы работаете над исходным кодом, используя Mercurial, вы:<br> <ol> <li>Делаете изменения</li> <li>Оцениваете, подходят ли они</li> <li>Если подходят, то выполняете

commit

</li> <li>Если не подходят, то выполняете

revert

</li> <li>GOTO 1</li> </ol><br> <br> (Я знаю. Пользуюсь командной строкой, в Windows, да еще и оператором GOTO — я <i>самый стрёмный программер</i> из всех, когда-либо живших.)<br> <br> Со временем вы можете забыть, на чем остановились и что поменяли с момента прошлого коммита. Mercurial отслеживает все это для вас. Все что вам нужно, это выполнить

hg status

и Mercurial даст вам список измененных файлов.<br> <br> <blockquote>

hg status

<br> отображает список измененных файлов.<br> </blockquote><br> <br> Предположим, я создал один файл, отредактировал другой и удалил третий.<br> <br> <img src="http://habrastorage.org/storage/3e908ca1/4cb8b4cf/daa03ab7/07f0f673.png"><br> <br>

hg status

отображает список измененных файлов, добавляя значок в начале каждой строки. Этот значок сообщает о том, что же произошло. «M» означаете «Modified» — файл был изменен. "!" означает отсутствие — файл должен быть здесь, но куда-то делся. "?" означает что, состояние не определено — Mercurial ничего не знает про этот файл. Пока не знает.<br> <br> Давайте разбираться с изменениями поочередно. Вот что поменялось в файле <b>a.txt</b>? Вы ведь можете забыть, что изменили. Чёрт, да я едва помню что я обычно ем на завтрак. А особенно внушает опасения то, что это всегда хрустящие колечки <a href="http://www.nestle.ru/products/breakfast/forchildren/cheerios/default.aspx">CHEERIOS</a>. В любом случае, a.txt изменен. Что поменялось?<br> <br> А есть команда для этого:

hg diff

сообщит вам в точности, что произошло с файлом с прошлого коммита.<br> <br> <blockquote>

hg diff

<br> показывает, что изменилось в файле.<br> </blockquote><br> <br> <img src="http://habrastorage.org/storage/cadb3342/3816d012/1d850a8a/8548d3b2.png"><br> <br> Формат результата немного непонятный, но самое важное, что вы можете видеть строки, начинающиеся с минуса (это то, что было удалено), и строки, начинающиеся с плюса (это то, что добавлено). Таким образом, вы можете видеть, что «Normal people» было заменено на «Civilians».<br> <br> Теперь про тот пропавший файл <b>favicon.ico</b>. Как уже было сказано, если вы на самом деле не планировали его удалять, то можете выполнить команду

hg revert

для восстановления. Но, предположим, что вы на самом деле хотели его удалить. При каждом удалении (или добавлении) файла вы обязаны сообщить об этом событии Mercurial.<br> <br> <blockquote>

hg remove

<br> помечает файлы как запланированные для удаления из репозитория. Файлы на диске не будут удалены до тех пор, пока вы не зафиксируете изменения.<br> </blockquote><br> <br> <img src="http://habrastorage.org/storage/1adbcbec/9083b063/0f042dfc/a90411e4.png"><br> <br> «R» означает «Removed», то есть, помечен для удаления. Во время следующего коммита Mercurial удалит этот файл. (<i>История</i> для этого файла сохранится в репозитории, так что, конечно, мы всегда сможем получить его назад.) И, наконец, нужно добавить этот новый файл <b>b.txt</b>:<br> <br> <img src="http://habrastorage.org/storage/c5e7f2af/f381ca0f/f30fd73b/48e0a4ff.png"><br> <br> «A» означает «Added», то есть, помечен для добавления. Заметили, что я разленился писать

hg status

каждый раз? Для Mercurial достаточно минимального набора букв, однозначно определяющего команду, а на

st

начинается только одна команда.<br> <br> Разобравшись с вопросиками и восклицательными знаками, я могу продолжить и внести изменения:<br> <br> <img src="http://habrastorage.org/storage/3304169d/c5c0285c/c62c0461/b51d2474.png"><br> <br> На что еще стоит обратить внимание в выводе

hg log

: строка <i>changeset</i> отображает номер каждого коммита. На самом деле даже два номера: короткий удобный вроде «0» для первой ревизии и длинный непонятный шестнадцатеричный, на который вы можете пока не обращать внимания.<br> <br> Запомните, что Mercurial хранит в репозитории достаточно информации для воссоздания любой версии любого файла.<br> <br> Прежде всего, при помощи простой команды

hg cat

вы можете вывести содержимое любой версии любого файла в консоль. К примеру, вот как увидеть, что сейчас находится в файле a.txt:<br> <br> <img src="http://habrastorage.org/storage/765630ca/414f3878/ec7f20ab/3bc776b0.png"><br> <br> <blockquote>

hg cat

<br> отображает содержимое любого файла для любой ревизии.<br> </blockquote><br> <br> Для того чтобы увидеть как файл выглядел раньше, я могу просто указать нужный номер набора изменений (changeset из лога) при помощи аргумента

-r

(«revision», то есть ревизия):<br> <br> <img src="http://habrastorage.org/storage/c268d14f/b5655b3d/3b7bf975/f3251569.png"><br> <br> Если у файла сложное содержимое или большая длина, а изменился он лишь немного, то я могу использовать команду

hg diff

с аргументом

r

для вывода разницы между двумя ревизиями. К примеру, вот как посмотреть разницу между ревизиями 0 и 1:<br> <br> <img src="http://habrastorage.org/storage/206febdc/576f891d/25c37414/7901a60f.png"><br> <br> И наконец,- надеюсь, что вы еще не свалились от усталости,- прежде чем закончить эту часть, я хочу показать вам еще <i>одну маленькую фишку</i>: при помощи команды

hg update

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

hg update -r 103994

и получить реально крутую версию ваших исходников. С гравицапой и прочими футуристическими штучками. Но, конечно, это невозможно.<br> <br> Что на самом деле возможно, так это вернуться к любой ревизии. Следите за руками:<br> <br> <img src="http://habrastorage.org/storage/0c666f35/3ec21ad5/a99e8dc1/86a101c4.png"><br> <br> <blockquote>

hg update

<br> приводит рабочий каталог к состоянию, как у заданной ревизии.<br> </blockquote><br> <br> Фактически, для перемещении вперед и назад между ревизиями

hg update

вносит в файлы запомненные изменения. Если файл был добавлен или удален, то эта команда добавляет или удаляет его на диске. Выполнение

hg update

без дополнительных параметров приводит рабочий каталог к состоянию как у самой свежей ревизии.<br> <br> <h5>Проверь себя</h5><br> <br> Отлично! Эта часть закончена. Вот все, что вы должны уметь делать на данный момент:<br> <ol> <li>Создать репозиторий</li> <li>Добавить или удалить файлы из репозитория</li> <li>После внесения изменений просмотреть, что было сделано, а затем</li> <li>… зафиксировать изменения, если они вам нравятся</li> <li>… или откатить изменения, если не нравятся</li> <li>Просмотреть предыдущие версии файлов или привести рабочий каталог к состоянию как у некоторой ревизии.</li> </ol><br> </html>

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