Лекция
Это окончание невероятной информации про mercurial .
...
любит что-либо удалять, так что вместо того чтобы затереть рецепт на свинском латинском, он переименовал файл:
А что если все зашло слишком далеко и вы уже закоммитили?
Есть команда hg rollback
, которая спасет вашу шкуру, но только если вы еще не протолкнули (push) ошибочный коммит в другой репозиторий. Эта команда отменяет один коммит.
hg rollback
отменяет один коммит, при условии, что вы не протолкнули его в другой репозиторий.
Представьте, что вы хотите поставить большой эксперимент в свободное время. Ваш босс нанял нового дизайнера, Джима. С тех пор дизайны, которые вы получаете, стали просто абсурдны. В них кислотный зеленый текст, ничего не выровнено (на это есть «художественные» причины, ага) и юзабилити хромает. Вы хотите прийти на работу в выходной и все переделать, но боитесь коммитить свои изменения, так как не уверены на 100%, что ваши идеи лучше, чем у этого рехнувшегося дизайнера. Джим курит траву практически все время с момента пробуждения до момента отхода ко сну. Вы не хотите использовать это против него, да и все думают, что эта привычка никого не касается до тех пор, пока дизайны в порядке. Но всему есть предел. Так ведь? И дизайны у Джима не в порядке, и вообще он дерзкий какой-то.
При работе с Mercurial вы можете просто создать клон всего репозитория:
Это не настолько расточительно, как может показаться. Так как в репозиториях recipes и recipes-experimentхранится одно и то же (пока), то Mercurial воспользуется "жесткими ссылками" (hard links). А значит, копия репозитория будет создана быстро и не займет много дополнительного места на диске.
Теперь можно сделать ряд изменений в экспериментальной ветке:
Начинаем мой великий эксперимент над рецептом гуакамоле:
В экспериментальный репозиторий можно коммитить без опасений:
Вы можете смело вносить изменения, фиксируя результат когда захотите. Это дает вам всю мощь контроля версий даже для вашего безумного эксперимента, причем никто не пострадает.
Если вы решите, что эксперимент не удался, то можете просто удалить весь каталог с экспериментальным репозиторием. Нет репозитория — нет проблемы.
Но если все получилось, то вам нужно лишь протолкнуть ваши новые правки:
И куда же они протолкнулись?
hg paths
отображает список известных удаленных (remote) репозиториев.
Строчка, начинающаяся с «default», содержит путь к репозиторию, в который hg push
проталкивает изменения если вы явно не укажете другой репозиторий. Обычно в этой строчке указан путь к репозиторию, с которого вы делали клон. В данном случае это локальный каталог, но в качестве пути может быть и URL.
Не забывайте, что проталкивание изменений в этот репозиторий...
… не приводит к тому, что изменения появляются в рабочем каталоге.
hg parent
отображает набор изменений, находящийся в рабочем каталоге.
Видите? Правки про «Queso» в пятом наборе изменений. Но в моем основном репозитории работа остановилась на четвертом наборе изменений. От того, что кто-то протолкнул изменения в репозиторий, рабочий каталог не обновился, и пятый набор изменений в нем не появился. Так что я по-прежнему работаю с четвертым набором изменений.
Если я захочу узнать, что в пятом наборе изменений, то мне нужно будет использовать команду hg update
:
Видите, что произошло? Изменения были получены, но они были после той версии, с которой я работал. Команды push
и pull
просто пересылают изменения между репозиториями. Эти команды не влияют на то, с чем я работаю в данный момент.
Сейчас репозитории выглядят так:
Mercurial гибок в вопросах пересылки изменений из репозитория в репозиторий. Можно протолкнуть изменения прямо из экспериментального в центральный репозиторий:
Так пятый набор изменений был отправлен из экспериментального прямиком в центральный репозиторий. Теперь, если я вернусь в свой основной репозиторий, то увижу, что в нем больше нечего проталкивать!
Это потому, что Mercurial знает, что в центральном репозитории этот (пятый) набор изменений уже откуда-то есть. Это по-настоящему полезно, потому как иначе Mercurial мог бы попытаться применить изменения заново и серьезно запутаться.
Дизайнер Джим, после того как ему предложили работу, пообещал приступить к делам сразу же. Однако он не появлялся на работе еще два месяца. Почти все уже забыли и о нем, и о том, что предлагали ему работу, так что когда он весь такой загорелый впервые появился в офисе, честно сказать, никто толком не мог понять, кто он и что вообще происходит. Это было достаточно забавно. Внешность у него типическая. В конце концов, во всем разобрались, но так как он был новеньким, все постеснялись спросить у него, что, черт побери, произошло. И про шрамы и синяки на лице тоже не спросили. Неважно. Просто мы ненавидим этого парня.
Иногда случается, что спустя месяцы, вы обнаруживаете, что сделали ошибку.
Картофельные чипсы? Че за..?!
Mercurial может изъять старый набор изменений из истории. Mercurial смотрит на набор изменений, определяет обратные действия и изменяет текущий рабочий каталог. Давайте попробуем изъять ту старую ревизию номер 2.
Матерь божья, что это было?
Вообще говоря, времени могло пройти много. Чипсы вообще могли исчезнуть из рецепта. Много всего жуткого могло произойти. А значит, иногда после изъятия ревизии объединить изменения невозможно. В таких случаях вы получите конфликты слияния (merge conflicts), которые вам нужно как-то разрешить. Вот об этом и поговорим в следующей части.
Вот то, что вы должны уметь делать после прочтения данной части:
Иногда при слияниях возникают конфликты. Обычно их легко разрешить. В любом случае их надо разрешить, или у вас будет несколько «голов». А кому это нужно?
Обеспечение слаженной работы нескольких людей над одним и тем же кодом — это важная функция системы контроля версий.
Представьте что и Роза, и я хотим внести изменения в рецепт гуакамоле. Роза работает над качеством авокадо. Перед тем как начать, она обновляет свой рабочий каталог, вытягивая свежие изменения из центрального репозитория.
Теперь небольшая правка:
Она фиксирует изменения и проталкивает их в центральный репозиторий:
В это же время я делаю изменение в другой части файла:
Я могу сделать коммит, но не могу протолкнуть изменения в центральный репозиторий.
Это, пожалуй, наименее полезное сообщение об ошибке в Mercurial. Лучше было бы так:
Так я и поступлю:
Хотите узнать, что за изменения только что были получены? Для этого есть удобный способ — команда hg log -P .
Ну точно, это те изменения, что сделала Роза. И что там с моим репозиторием сейчас?
У моего репозитория «несколько голов». По сути, мой репозиторий выглядит так:
Видите две головы? Они появились, потому что Роза сделала свои изменения, работая с седьмым набором изменений, и я тоже сделал свои изменения, работая с тем же набором. Так что теперь требуется слияние (merge). [Редактор подсказывает, что нельзя использовать пассивный залог] Я должен сделать слияние.
Команда слияния, hg merge
, взяла две головы и объединила их. После этого она поместила результат в мой рабочий каталог. Она не закоммитила его. Это дает мне шанс проверить, что результат слияния корректен:
Похоже на правду: авокадо сорта Хасс и перчики халапеньо. Так что я сделаю коммит и протолкну изменения на сервер.
Я проталкиваю два набора изменений: мои изменения про халапеньо и результат слияния, который тоже является набором изменений.
Обратите внимание на то, что в наших изменениях не было конфликтов, потому что Роза и я работали над разными частями рецепта. Потому слияние было супер-пупер простым. Это наиболее частая ситуация, потому что в большинстве организаций разные программисты работают над разными частями кода.
Иногда бывают странные организации, в которых никто не готов стукнуть кулаком по столу и все-таки разделить зоны ответственности. Это может спровоцировать неожиданное и часто необъяснимое чувство грусти среди программистов. Эту ситуацию непросто распознать. Но есть симптомы: программисты закрываются в туалетах, программисты закрываются в серверных, высокая текучесть кадров, звуки сдавленных рыданий в помещении, а также неожиданное повреждение барабанных перепонок из-за многократных выстрелов штурмовой винтовки.
НО, даже в самых замечательных организациях с наилучшим руководством конфликты при слиянии иногда случаются, и Mercurial потребует от того, кто делает слияние, разрешить конфликт. Давайте посмотрим как это делается.
Для начала… я хочу чтобы Роза была в курсе моих изменений про халапеньо:
Сейчас мы увидим что случается когда у вас на-сто-я-щий конфликт: мы оба немного накосячим с ингредиентами.
Я добавил банан:
И первым зафиксировал изменения:
А Роза, господи прости, добавила МАНГО в ТОМ ЖЕ МЕСТЕ рецепта.
«Зрелый молодой» манго, я не шучу.
В этот раз я первым зафиксировал изменения, так что теперь Розе придется заниматься слиянием. Ха-ха!
И вдруг, обнаруживается конфликт и выскакивает окошко какой-то программы для разрешения конфликтов со столь страшным интерфейсом, что только матери этой программы он может нравиться. Но программа обычно достаточно неплохо делает то, для чего предназначена, надо только разобраться как она работает. Наиболее распространенной программой для разрешения конфликтов в наше время является KDiff3, так что Роза увидит следующее:
В программе KDiff3 у вас есть четыре панели. Верхняя левая — это оригинальный файл. Верхняя средняя показывает Розе ее версию файла. Верхняя правая показывает Розе мою версию. Нижняя панель — это редактор, в котором Роза собирает итоговый файл по мере разрешения конфликтов.
Разрешать конфликты достаточно просто. Нужно пройтись по всем конфликтам и выбрать каким образом разрешить каждый из них. Роза сошла с ума и решила, что бананово-манговая гуакамоле не так уж плоха:
Кстати, я говорил вам, что Роза, похоже, кое с кем встречается? Как-то раз ее видели уходящей с работы с парнем, который выглядел примерно как Деннис Франц. В таком прекрасном настроении как тогда ее давненько не видели.
Роза сохраняет изменения и закрывает KDiff3.
И конфликт разрешен.
Вот что вам стоит запомнить: вы не обязаны проводить слияние, подстраиваясь под чье-либо расписание. Вы можете выполнять hg pull
когда угодно и, если не хочется сразу же разрешать конфликты, то можете свободно продолжать работать и счастливо коммитить до тех пор, пока не найдете время заняться слиянием.
Вот то, что вы должны уметь делать после прочтения данной части:
Mercurial позволяет очень гибко настроить репозитории. Плюс, так как слияния работают отлично и вы можете на них полагаться, можно иметь особые служебные репозитории в соответствии с требованиями процесса разработки в вашей команде.
Наш рецепт становится все лучше:
Давайте приглядимся к номеру набора изменений:
Первая часть номера, 13, короткая и удобная. Проблема в том, что… на нее нельзя полагаться!
При независимой работе членов команды и осуществлении слияний эти короткие номера могу начать отличаться у разных членов команды:
Так что на практике я не могу сказать: «Хорошо, давайте выпускать версию, собранную из 13 набора изменений», потому что у сотрудников может быть разное представление о том, что является 13-тым набором. Вот почему есть еще и тот безумный шестнадцатеричный номер.
Этот шестнадцатеричный номер уникален во всех репозиториях и никогда не меняется.
То есть я могу сказать людям: «Эй, сегодня релиз! 1b03ab783b17-ый набор изменений!». Согласитесь, было бы неплохо иметь возможность дать этому набору имя?
Ну, у вас есть такая возможность. Такое имя называется тег (или таг, от англ. tag).
Давайте теперь взглянем на лог:
Обратите внимание, что само добавление тега к набору изменений является набором изменений. Этот набор изменений автоматически фиксируется в репозитории (коммитится). Так что теперь каждый раз, когда я хочу сослаться на ту версию кода, что мы выпустили, я могу использовать Version-1.0 вместо 1b03ab783b17.
Замдиректора спустился с 31-го этажа для того чтобы поучаствовать в офисной вечеринке по поводу выпуска новой версии и принес ящик достаточно дорогого на вид игристого вина. Стэн немного напился. Ну, не то, чтобы немного. Вообще-то, это было что-то невиданное. Стэн снял рубашку и, показывая всем свои мускулы и солидное пузо, пытался произвести впечатление на дам из отдела маркетинга. Он хвалился: «Я буду подтягиваться на лампах» (у нас в офисе используются длинные лампы дневного света). В общем, он подпрыгнул, схватился за светильник и, конечно же, оторвал его вместе с лампами и потолочной плиткой. Неудивительно, ведь светильник весом в примерно 4,5 килограмма висел на паре проволочек, а вес Стэна как раз в том самом популярном диапазоне 130-135 килограммов. Повсюду было битое стекло и куски звукоизолирующей плитки. Стэн упал прямо на копчик и начал жаловаться, что засудит компанию за небезопасные условия труда.
Остальные вернулись на рабочие места для работы над Guac 2.0.
Коммит:
Не стоит и говорить, что этот рецепт пока сомнителен. Его не тестировали, к примеру. И тут звонит клиент.
«Слишком солено получается!», скулит клиент. И нет, он не желает подождать выхода версии 2.0 с исправлением ошибки.
К счастью, у нас есть тот тег. Я могу использовать hg up
для перехода к любой версии в репозитории.
Теперь я могу исправить эту тупую проблему с солью:
Затем:
Mercurial напоминает мне, что мои действия создали новую голову. Теперь в репозитории две головы: версия 2.0, над которой я недавно работал, и версия, которую я только что закоммитил.
В данный момент я могу отдать версию с последними изменениями клиенту, пометить ее как 1.1, и продолжить работать с версией 2.0.
Но есть одна проблема… исправления про соль отсутствуют в версии 2.0. Как мне это исправить?
Ну вот. Я должен сделать слияние тегов. Это известный баг в Mercurial. Проблема в том, что теги в Mercurial — это просто файл с именем .hgtags, для которого тоже ведется контроль версий. Поэтому время от времени вам нужно вручную делать слияние разных версий файла .hgtags. В такой ситуации ваши действия просты… нужно всегда сохранять ОБЕ версии каждой строки в файле.
Описанный выше простой способ перейти к старой, помеченной версии годится, если вам нужно сделать лишь одно маленькое незапланированное изменение в выпущенном коде. Но правда в том, что в большинстве программных проектов такие ситуации возникают постоянно, а у Mercurial есть более надежный способ разобраться с ними.
Так что я сейчас отменю все изменения, сделанные после 1.0, верну репозиторий в состояние, которое у него было в момент выпуска 1.0, и затем смогу показать вам модный надежный способ исправлять баги существующих клиентов и параллельно работать над новой версией.
Идея в том, что вместо работы с одним репозиторием мы заведем два репозитория. Один репозиторий назовемstable, а второй — dev.
В репозитории stable хранится последняя мажорная версия кода, отправленная клиентам. Каждый раз, когда вам нужно срочно исправить баг, вы делаете это в stable. В нашем примере, все патчи для версии 1.0 попадут в stable.
Репозиторий dev — это то место, где ведется разработка следующей мажорной версии, то есть версии 2.0.
Как только вышла версия 1.0, я клонирую stable в dev:
Теперь у меня два идентичных репозитория:
Так как история в обоих репозиториях одинакова до 14-го набора изменений включительно, то Mercurial воспользуется "жесткими ссылками" вместо того, чтобы делать две копии на диске. Поэтому операция hg clone
выполняется быстро и дешево, а значит, вы можете без колебаний делать много-много клонов репозитория.
Теперь начнем работать над guac в репозитории dev:
И исправим ту проблему с солью в репозитории stable:
Я помечу эту версию и выпущу ее как 1.1:
Теперь, время от времени, нам нужно втягивать изменения из stable в dev:
Вот что мы только что сделали:
И если вы можете понять, что нарисовано на этой безумной картинке, то с пониманием Mercurial у вас больше проблем не будет. Суть в том, что в репозиторий stable попадают только исправления ошибок, а в репозиторииdev хранится новый код и проводятся слияния с исправлениями ошибок.
Есть и другие применения нескольким репозиториям.
В больших сложно устроенных организациях вы можете комбинировать эти техники и настраивать цепочки репозиториев, вытягивающих изменения друг из друга. По мере того, как какой-то функционал проходит этапы тестирования и интеграции, он втягивается в репозитории по цепочке до тех пор, пока, наконец, не окажется в главном репозитории, хранящем код, который получают клиенты:
Вот то, что вы должны уметь делать после прочтения данной части:
Что ж, так получилось, что мы дошли до конца пособия. Я даже близко не подобрался к тому, чтобы описать все возможности Mercurial, но есть достаточное число материалов для углубленного изучения. Есть книга, которая описывает все крайне подробно. И если у вас есть какие-либо вопросы, то я приглашаю вас на сайтKiln Knowledge Exchange (это как StackOverflow, только для Kiln, и вопросы про Mercurial более чем приветствуются на этом сайте).
Выводы из данной статьи про mercurial указывают на необходимость использования современных методов для оптимизации любых систем. Надеюсь, что теперь ты понял что такое mercurial , сис контроля версий работы и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Разработка программного обеспечения и информационных систем
Часть 1 Mercurial — система контроля версий. Основы работы
Часть 2 Часть 5. Процесс слияния - Mercurial — система контроля версий.
Ответы на вопросы для самопроверки пишите в комментариях, мы проверим, или же задавайте свой вопрос по данной теме.
Комментарии
Оставить комментарий
Разработка программного обеспечения и информационных систем
Термины: Разработка программного обеспечения и информационных систем