Переход на DVCS, Mercurial

в 19:04, , рубрики: DVCS, Mercurial, svn, Песочница, метки: , ,

С какой целью и для кого

Данная статья является кратким изложением основных преимуществ DVCS.
Я собрал воедино все доводы о пользе перехода на DVCS (а именно mercurial) и постараюсь доступно изложить это для тех у кого не было практического опыта работы ни с одной из DVCS.

Мы производим программные продукты, сервисы все что угодно. И продуктом нашей деятельности является написанный код, который в процессе доставки до конечных пользователей проходит ряд определенных стадий: сделали коммит, все, положили на конвейер, оно поехало дальше. Организация рабочих процессов с применением систем контроля версий может отражать этапы процесса разработки. Почему? Можно рассматривать систему контроля версий как некий «конвейер производства», по сути он именно и выполняет роль конвейера: код который должен попасть на тестирование попадает сначала в ветку testing, здесь код обкатывается, если все нормально он едет дальше если не проходи тестирование он отваливается обратно.

Зачем переходить на распределенные системы? Радости перехода

Локальная работа

Первая причина которая указывается во всех источниках, это возможность работать локально.
Другая первая причина — это скорость. Может показаться смехотворным: “Ну какая вам скорость простите нужна при коммите или апдейте или других операций которые вы производите”. Это так, на самом деле не так часто в централизованных системах контроля ревизий вы коммитите и не так часто апдейтите ну или производите другие манипуляции с удаленным репозиторием. Но тут палка в 3-х концах. Во первых, DVCS подталкивают вас гораздо более тесной работе с репозиторием. Во вторых, разница в скорости она разительна. Здесь не надо вообще задумываться о произведении практически любых операций и скорость не измеряется вообще никак, то есть скорость мгновенна.

Локальные коммиты

Локальные коммиты порождают частые коммиты. Чем это хорошо? Более глубокая история, более гранулированные изменения и проще понять чего наделали вы или наделали другие. Локальный репозиторий исключительно ваш. Пока вы не произвели синхронизацию с центральным репозиторием при этом ваш репозиторий мало привязан к удаленному. Позволяет это делать разные вещи со своим репозиторием, в самом экстренном случае если чего наделали — удаляем его и берем заново из центра, это конечно крайний случай который возникает когда вы не очень представляете чего вы делаете. Локальные откаты, когда нужно вернуться на предыдущую ревизию, можно это сделать гораздо менее болезненно чем в SVN. Локальная работа имеет еще один большой плюс. В централизованных системах контроля версий (к ним относится SVN) commit за частую — дело ответственное, действие сильно осмысленное к которому сильно готовятся. Люди бояться делать коммиты и делают их мало.

Иерархии доверия

Возможность построения иерархии доверия. Они важны в случае разработки проекта корпоративного, особенно в случае разработки проекта с большим количеством участников и с разным качеством. Скажем если есть Open Source проект где появляется на стороне человек которого вы знать не знаете хочет вам помочь, и может действительно чем-то поможет. Иерархии доверия позволяют вам создать отношения между множественными локальными репозиториями. Вы можете довольно просто и предсказуемо брать только от тех кого вы хотите и разрешать вам пушить только тем кому вы уж особо доверяете. Процесс push — это новая терминология DVCS. В случае с SVN коммит происходит в главный. В DVCS если кто-то запушил в ваш локальный репозиторий вы можете взять этот апдейт, рассмотреть его со всех сторон, протестировать и только потом принять решение подходит ли он для вашей системы и достоит ли он того чтобы вы его запушили в интеграционный репозиторий.
Иерархические эти отношения они с одной стороны конечно хороши, с другой стороны они усложняют всю концепцию и усложняют вашу жизнь. Если иерархия не продумана до конца и не построена как следует, вы можете столкнуться с ситуацией когда для осуществления того чего вы хотите необходимо будет произвести цепочку операций. Ну если вы например не определились толком кому чего можно, но технически это «кому» и «чему» ограничено, возможно вам придется сначала пушить в одно место, потом из этого места апдейтиться и пушить в другое. Согласитесь, занятие не здоровое. Ну и несомненно использование системы точка-в-точку, то есть точка в центр, когда вы — точка вторичная а центр тот главный неповторимый и вы в него можете только коммитить и только апдейтить, она на первый взгляд более вменяемая более простая.

Модель «Проект на репозиторий»

Форсирование модели «проект на репозиторий» это еще один плюс который трудно переоценить. В SVN такая общая практика: у вас один проект, в нем бранчи, таги и транк. Вот туда вы все коммитите. На практике такое бывает мягко говоря не всегда. SVN как система которая может покрыть собой любой сложности дерево и работать примерно одинаково, одни скажут хорошо другие скажут одинаково плохо, с любой сложностью систем директорий, так вот она провоцирует вас к тому что хорошо бы иметь репозиторий на какую-то область деятельности. То есть создаются несколько областей которые между собой не пересекаются. Это еще одна проблема, не знаю как она решена в современном svn-е, но долгое время не было никакой возможности вменяемой связывать между собой проекты в разных репозиториях для того чтобы делать чего-то общее. Ну грубо говоря из проекта который контролируется одним репозиторием который присутствует там, закоммитить в другой. У многих очень разухабистая система и чуть ли не вся ваша разработка, все ваши проекты находятся в одном месте и физически хранятся на одном сервере и в одном репозиторие.
В любых DVCS это не будет работать (один репозиторий на проект). Здесь выхода практически нет. Хочешь не хочешь вам придется организовывать один проект на репозиторий. Это имеет ряд своих плюсов, ряд своих минусов, но плюсы сильно перевешивают. Концептуально и сущностно это чувствуется как правильное решение. Чисто с технической и безопасной точки зрения это тоже видится правильным решением т.к. вы можете настроить например, один из практических случаев, права только для одного репозитория одной группе разработчиков а права на push в другой репозиторий совсем другой группе и они могут между собой не пересекаться. То есть одним можно отсюда только читать, другим от туда можно только читать а сюда писать. Понятно что имеется ввиду — разделение прав по проектам.

В случае деплойментов, деплойменты которые поставляют исходный код, во многих отношениях безопаснее. Когда деплоймент происходит самым примитивным образом, то что в svn делается svnup-ом или svncheckout-ом здесь это безопаснее. Вам трудно, даже невозможно взять на боевой сервер или на какой-то «опасный» сервер больше чем вы хотите взять. Возьмете только один репозиторий тот самый который вы деплоите, а мы помним что репозиторий является синонимом слова «проект», то есть в худшем случае пострадает ваш проект. Есть еще целый ряд плюсов, прежде всего отсутствие вложенных .svn подкаталогов которые хотя svn так больше не делает, но тем не менее у многих версия до 1.6.
Есть один каталог высоко-уровненный .hg каталог, и не появляются эти служебные подкаталоги во всех местах где надо и не надо и риск того что в них проникнет злая рука уменьшается из-за того что каталоги эти в одном месте и место надо защитить всего одно а не в каждой поддиректории.
Поскольку сами по себе проекты являются отдельными папками, вы можете легко их копировать с места на место и переносить по своей файловой системе. Это известная проблема в svn-е когда вы сначала чекаутите проект высокого уровня а потом манипулируете внутри под проектами. Это вызывает целый ряд проблем. Идея перемещать руками каталоги внутри контролируемой svn-ом иерархии это очень плохая идея и может привести к массе головных болей и потребует специалиста который очень хорошо представляет как там в svn все работает чтобы потом ситуацию разрулить.

Надежность доставки ревизий

Еще одним плюсов подобных систем называют «подписывание» или «подписка ревизий электронной подписью», ну грубо говоря считается той или иной надежности хеш который потом используется при всех операциях как средство контроля целостности данных. Речь идет об integrity check (контроль целостности данных), не о секретности и защитах от нападения. Что важно и то что действительно практично, система вам гарантирует доставку не разрушенных данных.

Вменяемая модель веток. Merge, branch (сливание, ветки)

Подошли к главному достоинству, к тому самому что подталкивает людей к переходу на DVCS.
Вот в чем проблема. Проблема в том что в системах с центральными серверами (svn) есть сложность и совершенно признаваемая и разработчиками и пользователями сложность ветвлений и поддержки этих ветвлений. Поддержка означает, если вы сделали ветвление, потом из этих веток надо брать, в них надо класть их надо сливать-разливать, производить все что можно себе представить в разухабистом дереве. И сейчас механизм очень далек от идеала, требует от вас сильного понимания того чего вы делаете, зачем вы делаете, выдерживания последовательности действий и происходят зачастую очень мистические случаи. Можно допустить что это вина программиста который мистику допустил, но интернет пестрит криками о том как люди пытаются мерджить и как у них это получается странно. На практике в настоящий момент количество людей которые активно работают с ветками в SVN, не велико. А те отщепенцы которые сидят на svn-е и активно работают с ветками, те избегают мерджи как могут.
Merge, branch в DVCS — простота совершенно необыкновенная. И работает это, ну просто работает. То что работает в subversion трудно назвать рабочей конфигурацией. И это не связано с тем что одни разработчики умнее, другие глупее, одни предусмотрели другие нет. Дело в том что концептуально система распределенная она сильно завязана на ветвление и потом на слияние этих изменений. Ну простой пример, если вы оба со своим коллегой берете из какого-то места определенную копию репозитория и работаете с ней независимо, коммитите туда постоянно и проводя свои гениальные изменения, при попытке залить это обратно вы столкнетесь с тем что последовательная в простейшем случае модель, когда одна ревизия сменяет другую она не будет выглядеть так последовательно в том месте куда вы слили. Особенно это заметно если вы время от времени пушите, время от времени берете от туда ревизии, короче говоря ситуация многоголовости здесь не является чем-то особенным, какой-то проблемой, является вполне рабочей ситуацией. То есть хочется сказать что в системах распределенных если нет нормального слияния и нормального ветвления все это работать просто не будет. Переключение между ветками сделано крайне просто.

Доступ к репозиторию по ssh

Может быть полным или контролируемым, это уже решать администратору. Можно напрямую по ssh доступаться к тому удаленному репозиторию к которому вам нужно доступиться и в зависимости от прав вы можете туда пушить, можете оттуда пулить.

Простота развертывания интеграционных и центральных репозиториев и репликаторов

Никаких особых проблем поднять удаленный репозиторий который будет принимать ваши пуши или отдавать вам пулы — нет.

Теоретически лучшее scalability

Некоторые хвалят DVCS за лучшее scalability. То есть их можно проще расширить когда по каким-то причинам один сервер уже не справляется, легко подключить 2, 5 и 10. Какое-то лукавое преимущество, потому что на практике не замечал настолько уж узких мест, чтобы сервер был затычкой. Здесь требование к серверу к тому что является «центральным» (потому что он такой же центральный как и ваш, просто к нему все доступаются) репозиторием, требования по доступу к нему, и по производительности гораздо более щадящее. С ним общаются совсем не часто.

Что вы теряете при переходе на DVCS

Капля дегтя. Потеря простоты модели

Самое первое что вы теряете, и серьезная конечно потеря, это потеря простоты модели. Если в svn все просто, есть место куда вы коммитите, есть место откуда вы апдейтите его состояние понятно и более-менее предсказуемо, теперь модель совсем поменялась. У вас какое-то множество независимых репозиториев. Даже продвинутые специалисты которые все теоретически вроде поняли на практике втыкаются в эту усложненную модель лбом, например идея того, что твой репозиторий совсем не такой как мой и мой номер версии совсем ничего общего не имеет с твоим номером версии — не так легко укладывается в голову.

Условный минус — надо читать доки

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

Способы делать branch

Коронный путь это делать клоны. Речь идет о том что если у вас есть репозиторий в месте А то вы сможете сделать клон в место В, работать с ним, коммитеть и в момент клонирования эти 2 копии абсолютно никак не связаны, вы можете параллельно работать над разными копиями. Это пример самого примитивного бренча. Мерджить потом тоже совсем не сложно, потому что вы можете из репозитория А сделать pull репозитория В а потом стандартным путем сделать Merge. Главное достоинство этого пути, тут сложно чего-то напутать. У вас есть 2 разных места они независимы и для того чтобы переключиться из места одного в место другое (из одного бренча в другой бренч) вам надо делать вполне осознанные действия. Легко собственно избавиться от такого бренча потому что делать ничего собственно для этого не надо, вы можете либо просто про него забыть, либо просто его удалить на уровне файловой системы и все, и нету бренча. После того как вы поработали, естественно смерджили все, его можно удалить, и никаких следов этого самого бренча нигде не останется.

Недостатки этого способа тоже есть, и некоторые из-за этих недостатков подобным способом практически не пользуются. Во первых отдельно стоящая копия репозитория с точки зрения управления проектами иногда хлопотная вещь. Возможно то, в чем вы разрабатываете программу не очень любит когда у вас проекты прыгают с места на место, когда вы переключаетесь на какую-то тестовую или девелоперскую версию или нестабильную версию и это требует изменение пути к проекту, ну в некоторых ситуациях это не очень удобно. Вторая проблема в том что если вам надо этот репозиторий сделать доступным вам необходимо пушить 2 раза. То есть вам необходимо пушить свой основной репозиторий и пушить этот. Они настолько независимы что это уже создает определенные проблемы, и поддержка этих 2-х версий требует двойного телодвижения, я имею ввиду 2-х бранчей. И для большого репозитория брать клон может быть накладно хотя тут есть оптимизационные технологии, то есть если ваш сервер далеко, не надо брать клоны 2 раза из удаленного сервера достаточно взять один в место А а потом из места В сделать клон места А. Mercurial достаточно умен для того чтобы не копировать файлы локально он делает линки, в этом случае экономится и место на диске а самое главное скорость для больших репозиториев это может быть существенно.

Вторым способ (тоже условного) бранчевания, является бранчевание bookmark-ами, то есть вы можете любую ревизию обозвать как-то и начать работать с этой ревизией. В принципе если вы понимаете концепцию многоголовости, все эти способы примерно об одном — «Вы ведете разные головы». В случае бранчевания bookmark-ами вы просто одну из голов называете как-то чтобы вы могли вспомнить, например branch А, работаете с ней. Строго говоря вам вовсе не обязательно ее как-то называть если вы способны запомнить ее номер-идентификатор вы можете работать с ней анонимно и это очень похожий способ еще одного бренчивания когда вы головы не называете никак просто апдейтитесь (здесь “апдейт” означает “переключиться на голову”) до определенной ревизии до определенной головы и работаете с этого места. Bookmark-и всего лишь оптимизация этого способа для того чтобы вы не забыли чего вы имели ввиду. К сожалению как bookmark-и так и анонимный способ бранчивания лишен переносимости. История этих бренчей теряется полностью, bookmark-и полностью локальные. И если вы чего-то такое делали, сделали bookmark-и и через 3 года решили вернуться и разобраться то этого как-бы бренча нет в природе. В вашем локальном репозитории он будет присутствовать, но если вы пушите куда-то удаленно, синхронизируетесь — то все сливайте воду, информация скорее всего будет потеряна. Ну говоря про то что бренчивание bookmark-ами неудобно, нельзя и о достоитнствах сказать. Во первый это очень быстрый и очень понятный способ. Это гораздо более понятный способ чем делание клонов хотя почему-то клоны считают путем по умолчанию. Они все расположены в едином месте, то есть вы не делаете физических копий (клонов) они легко удаляемы. То, что они легко удаляемы было упомянуто 2 раза, с точки зрения достоинств и с точки зрения недостатков. Такой вот дуализм жизни.
Именованные бренчи, упомянутые выше, практики говорят это самый правильный способ, то что называется hg branch — этот способ на их взгляд логичен, понятен и вполне безопасен в отличии от клонов вам не надо вести 2 параллельных дерева разработки и эти 2 дерева как-то сопровождать, не надо отражать эти изменения с вашей среде, то есть ваш проект находится в одном месте, просто время от времени вы переключаете его либо в один branch либо в другой branch. Переключение элементарное, делается при помощи стандартной комманды update с указанием имени бренча.
Естественно и в этом способе как и в остальных переключение делается очень быстро с одного бренча на другой, они глобальные и они вечные, то есть информация о бренче является частью стандартной мета-даты (мета-информации) mercurial который предоставляет, и информация о бренчах там всегда будет (в отличие от git). Если вы пушите свой репозиторий эта информация тоже пушится при любых клонах при любой переносимости это переносится и на мой взгляд является правильным путем и даже трудно назвать это особым достоинством вот так оно работать и должно.
Из недостатков этого способа — считается их 2. Некоторые говорят это сложный способ, не очень понятный (сложно с этим согласится). Вторым недостатком является то, что немножко портит это концепцию предупреждений и слежении за собой с точки зрения излишней многоголовости. Когда вы пытаетесь впушить нечто что доставляет новую голову, в том случае если эта новая голова часть вашего основного бренча, в этом случае наверное есть о чем задуматься. Конечно зависит от вашей логики, от ваших соглашений. Но когда вы создаете новый бренч и первый push вам скажет что хорошо бы тебе сделать "-f" потому что создается новая голова. В этом случае вы именно и собирались создать новую голову и такое сообщение может немножко удивлять и настораживать, «чего это оно такое ругается я вроде делаю все правильно».

Пожалуй на этом недостатки закончены. А с точки зрения мерджинга (сливания) этих бренчей оно практически одинаково во всех случаях. То есть вам надо каким-то образом доставить информацию, ну если это клон вы делаете pull, в остальных случаях вы делаете merge указывая с какой головой или с каким бренчем вы это сливаете и собственно все. С этого момента все одинаково для всех способов разветвления и слияния. Надеюсь что я как-то описал случаи когда переход этот имеет смысл. Люди перешедшие на DVCS считают что переход этот имеет смысл и смысл был огромен и ни минуты не жалеют о том что оставили svn и познакомились с новым и прекрасным миром DVCS.

В дополнение

Rebase

Проблема с rebase. Почему это плохо? Информация теряется. Это такая вещь которая сразу с первого взгляда с не очевидными результатами и не очень понятно зачем это делать. Чтобы избежать большое количество коммитов из серии «я уже почти сделал фичу 1», «я уже почти сделал фичу 1 на 85%» и т.д. Эта фича позволяет вам сделать 1 коммит на 1 фичу и запушить ее. Опаснисть rebase не в том что мы объединяем несколько своих коммитов в один, это в общем-то не rebase, а базовая операция. Опасность rebase заключается в том что мы сделали 10 коммитов сами и мы взяли апдейт с репозитория и там сделал 10 коммитов Петя. Вот если мы честно мерджимся то мы видим что: вот у нас репозиторий точка ветвления, Петины изменения, ваши изменения и вот в какой-то точке они сошлись, получился один исходник. Если мы делаем rebase мы делаем следующее. Мы соответственно заставляем систему управления контроля версиями забыть о том что мы наши изменения делали параллельно с Петей и пересаживаем их поверх изменений Пети, вот, после чего результат коммитим в систему контроля версий. При этом вот этот вот процесс «пересаживания» он нам делает некий «промежуточный» коммит который в код делает некие изменения дабы синхронизировать состояние после Пети и до нас. При этом соответственно чудовищно теряется история, то есть когда мы на такой «сплющенный» коммит в будущем смотрим мы не можем определить что это делалось параллельно с Петей и в чем собственно говоря была причина такого мерджа.
Каким образом можно потерять историю когда делается rebase? Есть такая вероятность потерять историю. Вот вы сделили rebase в определенной ветке на определенной ревизии а другой разработчик после этого момента с вашей ветки произвел branch (отпочковался) тогда не очевидно становится. Это в случае когда оба разработчика работают с публичной веткой, для нее историю нельзя переписывать. Во избежании подобных путаниц для публичных веток не делают rebase, rebase деалют только на своих приватных ветках.

Функциональный шелл

Функциональный шелл — ценная штука. Предположим мы делаем какую-то фичу, пишем код… пишем… пишем. Вдруг видим в коде баг, у нас уже внесены какие-то правки в этом коде. Далее у нас есть несколько вариантов, мы можем исправить баг и закоммитеть все вместе, это все плохо. Мы можем куда-то сохранить свои изменения исправить баг отдельным коммитом а потом восстановить изменения и т.д. ну или другие кривые способы. Меркуриловский extention shelve делает следующее. Мы писали фичу вдруг нашли баг, нажали кнопочку shelve спрятали наши изменения, у нас рабочая копия выглядит как она была до внесения изменений. И мы правил баг, комитим его, после чего нажимаем unshelve и к нам возвращаются наши изменения, мы видим наши изменения но уже с исправленным багом. Доделываем наши изменения после чего комитим их.

Менеджеры управления репозиториями

Есть для mercurial менеджеры управления репозиториями. Позволяют искать файл проекта, искать по комментарию или по содержимому:

rhodecode — на сайте есть демо, можно посмотреть в действии.
phpHgAdmin
встроенный light-weight web server
hGate
Все решения бесплатны.

P.S. Помощью изложенного материал служили подкасты Умпутуна и доклад Артура Орлова

Автор: SuicideBlonde

Источник

Поделиться

* - обязательные к заполнению поля