0,0
рейтинг
19 ноября 2010 в 12:20

Разработка → Hg Init: Часть 1. Переобучение для пользователей Subversion перевод

Hg Init: Учебное пособие по Mercurial.


Mercurial — это современная распределенная система контроля версий с открытым кодом. Эта система — заманчивая замена для более ранних систем вроде Subversion. В этом простом учебном пособии в шести частях Джоэль Спольски (Joel Spolsky) рассказывает о ключевых принципах Mercurial.

Если вы использовали Subversion, то Mercurial будет непонятным. Эта часть рассказывает о главных отличиях при работе с Mercurial. Если вы никогда не использовали Subversion, то можете просто пропустить эту часть.

Часть 1. Переобучение для пользователей Subversion


В каком же я был смятении, когда программисты в моей компании решили сменить Subversion на Mercurial!

Для начала, я начал приводить всевозможные тупые причины, по которым нам не надо ничего менять. «Мы должны хранить репозиторий на центральном сервере, так безопаснее», — сказал я. Знаете что? Я был неправ. При работе с Mercurial у каждого разработчика на жестком диске хранится полная копия репозитория. Это, на самом деле, безопаснее. В любом случае, почти в каждой команде, использующей Mercurial, центральный репозиторий тоже существует. И вы можете делать резервное копирование этого репозитория со всей необходимой одержимостью. А еще можете устроить трехступенчатую защиту с Сайлонами, Штурмовиками и прелестными лабрадудлами или что там требует ваш IT-отдел.



«Проблема с распределенными системами контроля версий в том, что они позволяют слишком легко делать ветки (branch)», — сказал я. «А ветки всегда приносят проблемы». Получается, что тут я тоже был неправ. Волна такая пошла. Ветки несут проблемы при работе с Subversion, потому что Subversion не хранит достаточно информации для того, чтобы слияние (merge) нормально работало. В Mercurial слияние безболезненно и легко, а потому ветвление распространено и безвредно.

Потом я сказал: «Хорошо, я буду использовать эту систему, но не ждите, что я смогу в ней разобраться». И я попросил Джейкоба сделать для меня шпаргалку, в которой будет все, что я обычно делал в Subversion, с указанием аналогов в Mercurial.

Я могу показать вам эту шпаргалку, но не буду, потому что она несколько месяцев мешала моим мозгам перестроиться.

Получается что, если вы использовали Subversion, то ваша голова немного… Э-э-э, как бы помягче сказать? Вы ранены во всю голову! Нет, не получилось. Вам нужно переобучение. Я ходил таким раненным полгода и думал, что Mercurial более сложен, чем Subversion. Но это потому, что я не понимал, как новая система на самом деле работала. Как только я понял, как она работает, оказалось — опа! да это достаточно просто.

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

Если вы никогда не использовали Subversion, то можете перейти к следующей статье («Основы Mercurial») и ничего не упустите.

Готовы? Хорошо, начнем с короткого опроса.

Вопрос первый: Вы всегда с первого раза пишите идеальный код?


Если вы ответили «Да» на первый вопрос, то вы врун и жулик. Получите «банан» и приходите на пересдачу.

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

И вот, как работает Subversion:
  • Когда вы вносите новый код в репозиторий, его получают все.


Так как весь новый код, который вы пишите, содержит баги, то у вас есть выбор.
  • Вы можете вносить глючный код и сводить людей с ума, или
  • Вы можете придерживать новый код до тех пор, пока полностью его не отладите.


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

Как пользователи Subversion, мы настолько привыкли к этой дилемме, что трудно представить себе систему, где эта дилемма не существует.

Команда, использующая Subversion, часто днями или неделями ничего не добавляет в репозиторий. В таких командах новички боятся залить что-то в репозиторий из-за опасения поломать билд, или разозлить Майка, ведущего разработчика, или по сходным причинам. Майк однажды так рассердился из-за изменений, которые поломали билд, что ворвался к практиканту, смахнул все с его стола и проорал: «Это твой последний день!». Этот день не был последним, но бедный практикант практически намочил штаны.

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

Вот простая иллюстрация жизни с Subversion:


При работе с Mercurial у каждого разработчика свой собственный репозиторий, живущий у них на компьютере:


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

Когда код надежен, и вы хотите дать другим его использовать, вы проталкиваете (push) ваши изменения из своего репозитория в центральный репозиторий. Из центрального репозитория каждый вытягивает (pull) общие изменения и рано или поздно все получат ваш новый код. Когда он готов.

Mercurial разделяет момент внесения кода в репозиторий и момент получения этого кода всеми остальными.

И это означает, что вы можете коммитить (hg com), но все остальные не получат ваши изменения. Когда у вас накопятся изменения, которые вас устраивают, которые стабильны и все круто, вы проталкиваете (hg push) их в главный репозиторий.

Еще одно большое концептуальное отличие


Вы знаете, что у каждой улицы есть название?

Ну, оказывается что в Японии это не совсем так. Японцы обычно просто нумеруют кварталы между улицами и только очень, очень важные улицы имеют названия.

У Subversion и Mercurial есть сходное различие.

В Subversion мыслят ревизиями. Ревизия — это то, как выглядит вся файловая система в определенный момент времени.

В Mercurial вы мыслите наборами изменений (changesets). Набор изменений — это четкий список изменений между двумя соседними ревизиями.

Шесть того или полдюжины этого — в чем разница?

Вот в чем разница. Представьте, что вы и я вместе работаем над каким-то кодом. И мы сделали ветки этого кода, и каждый пошел на свое место и сделал много-много независимых изменений в коде, так что ветки достаточно сильно разошлись в разные стороны.

Когда нам нужно сделать слияние, Subversion смотрит на обе ревизии — мой измененный код и ваш измененный код — и пытается угадать, как слепить их вместе в один большой страшный бардак. Обычно Subversion это не удается, и получаются длинные списки конфликтов («merge conflicts»), которые на самом деле не конфликты, а просто места, в которых система не смогла разобраться в наших изменениях.

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

Если, для примера, я немного изменил какую-то функцию и перенес ее куда-то, то Subversion на самом деле не помнит этого. Так что когда дело дойдет до слияния, она просто может решить, что в коде из ниоткуда появилась новая функция. В то же время, Mercurial запомнит: функция изменилась, функция переместилась. Это значит, что если вы тоже поменяли эту функцию, то вероятность того, что Mercurial успешно проведет слияние наших изменений, гораздо больше.

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

Если все это кажется вам немного запутанным — не переживайте. По мере чтения этого пособия все обретет ясный смысл. В данный момент самое главное, что вам нужно знать: из-за того, что Mercurial оперирует наборами изменений, а не ревизиями, слияние кода в Mercurial работает гораздо лучше, чем в Subversion.

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

Хотите узнать кое-что забавное? Почти у каждой команды, использующей Subversion, с членами которой я разговаривал, есть некий вариант одной и той же истории. История настолько часто встречается, что я просто назову ее «Главной историей про Subversion». Вот эта история: в определенный момент они попробовали сделать ветку в развитии кода. Обычно для того, чтобы версия, которую отдали клиентами, была отделена от версии, с которой возятся разработчики. И все рассказывали мне, что когда они попробовали сделать это, то все было отлично до момента, когда им нужно было сделать слияние. И слияние было кошмаром. То, что должно было быть пятиминутным процессом, превратилось в шесть программистов вокруг одного компьютера, работавших две недели, пытаясь вручную внести каждый багфикс из стабильной ветки в ветку разработчиков.

И почти в каждой команде мне сказали, что они поклялись «больше никогда» и отказались от веток. И теперь они делают так: каждая новая фича в большом #ifdef блоке. Так они могут работать всегда в стволе репозитория, а клиенты никогда не получают новый код пока он не отлажен, и, откровенно говоря, это нелепо.

Отделять стабильный и разрабатываемый код — это именно то, что система контроля версий должна позволять вам делать.

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

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

Это означает, что у вас могут быть репозитории для службы тестирования, где команда тестеров пробует новый код. Если он работает, то служба тестирования вносит изменения в центральный репозиторий, что, в свою очередь, означает, что в центральном репозитории всегда надежный протестированный код. И это работает!

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

И последнее большое концептуальное отличие


Последнее важное концептуальное отличие между Subversion и Mercurial не такое уж и важное, но оно может поставить вас в неудобное положение, если вы не будете про него знать. Вот оно:

Subversion, по сути, система контроля изменений для файлов, а в Mercurial контроль изменений применяется ко всему каталогу, включая все подкаталоги.

Главным образом, это проявляется так: в Subversion, если вы находитесь в подкаталоге и вносите свои изменения в репозиторий, то вносятся только изменения из этого подкаталога и всех его подкаталогов. Это может привести к тому, что вы забудете внести изменения из другого подкаталога. А в Mercurial все команды всегда применяются ко всему дереву каталогов. Если ваш код находится в c:\code, то когда вы выполняете hg commit, то можете находиться в c:\code или в любом подкаталоге — результат будет одним и тем же.

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

И напоследок...


Теперь часть, где вы просто должны поверить мне на слово.

Mercurial лучше, чем Subversion.

Лучше, если работать над кодом в команде. Лучше, если работать над кодом в одиночку.

Просто лучше.

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

И поначалу вас будет искушать мысль — я знаю, будет, — бросить Mercurial и вернуться к Subversion. Потому что будет странно, словно вы живете в чужой стране, и вас будет тянуть на родину, и вы будете придумывать всевозможные оправдания вроде того, что будете заявлять, что в Mercurial рабочие копии занимают слишком много места, что есть туфта, так как на самом деле они занимают меньше места, чем в Subversion. Это правда!

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

И после этого вы попросите Джейкоба, или кто там у вас эквивалент Джейкоба в вашем офисе, дать вам шпаргалку «От Subversion к Mercurial», и вы потратите три месяца, думая, что hg fetch это как svn up, не понимая, на самом деле, что делает hg fetch, и однажды все пойдет не так, и вы будете винить Mercurial, хотя вам стоило бы винить себя за непонимание того, как работает Mercurial.

Я знаю, вы так и сделаете, потому что это то, что я сделал.

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

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

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

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

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

  • +20
    Уговорил!
  • +1
    Спасибо большое. Читал в оригинале, но мой английский оставляет желать лучшего…
  • +7
    Интереснее былобы посмтреть на сравнени с git. Я сам Mercurial не пользовался ниразу, но догадывался что он схож с git. А то что git в разы удобнее чем subversion я в принципе познал на практике.
    • +1
      По мне так это вопрос привычки, хотя конечно отличия есть, вот кое что по теме proft.com.ua/2010/10/17/spravochnik-po-git-i-mercurial/
      • +4
        Почитал материал по ссылке, за что большое спасибо. В принципе, как подметил мой товарищ, единственное преимущество, которое он заметил это то, что в «hg» буковок меньше чем «git» )
        • +1
          Субъективно лично мне кажется hg как-то быстрее работает, хотя это возможно потому что с git работал лишь в windows с прослойкой cygwin, да и было это несколько лет назад.
          • 0
            по нашим наблюдениям git очень тормозит под виндой на больших репозиториях
        • –3
          git работает в разы быстрее, т.к. не на скриптовом языке написан
          • +1
            вот здесь бы не помешала ссылка на воспроизводимый бенчмарк
            • –2
              Вот вам батнички:

              test-git.bat
              @echo %TIME%
              @git init
              @git add .
              @git commit -q -m initial
              @echo %TIME%
              


              test-hg.bat
              @echo %TIME%
              @hg init
              @hg add -q
              @hg commit -q -m initial
              @echo %TIME%
              


              Берем проектик на пару сотен файлов, выполняем батнички несколько раз…

              Сразу становится видно, что hg в полтора-два раза медленнее git
              • +3
                Этот бенчмарк показывает, что git коммитит стопицот файлов в полтора раза быстрее, чем hg. И всё. К повседневной работе этот «бенчмарк» отношения не имеет. Попробуйте что-нибудь другое.
                • –1
                  По-вашему commit к повседневной работе отношения не имеет?

                  Мощно, ладно еще понимаю push… Но commit, я лично десятки раз в день делаю…

                  Вы никогда не задумывались, какой смысл было разрабатывать git, когда есть hg?
                  Такой же опен-сорсный и распределенный?
                  • 0
                    commit, я лично десятки раз в день делаю
                    и сколько файлов за раз вы коммитите?
                  • +3
                    Вы никогда не задумывались, какой смысл было разрабатывать git, когда есть hg?
                    единственное реальное преимущество, которое имеет git перед hg — это возможность мергать одновременно более двух веток. Для Линуса и проектов уровня ядра Linux, с сотнями контрибьюторов и веток это killer feature.
                    • –5
                      Т.е. Mercurial это как Windows Vista, тем у кого еще SVN (Windows XP) можно пропускать и сразу ставить git (Windows 7)
                      • +2
                        Нет ли в этом комментарии Windows головного мозга?
                        И да, вы забыли о прочих преимуществах mercurial над git. Кроме того, мне кажется, что разработчики Python пилят его под Windows по остаточному принципу.
                  • 0
                    pull в разы быстрее работает в hg, чем в git, по моим наблюдениям
                  • 0
                    > Вы никогда не задумывались, какой смысл было разрабатывать git, когда есть hg?
                    Такой же опен-сорсный и распределенный?

                    Возможно потому, что они появились одновременно, с разницей чуть меньше двух недель?
          • +4
            А по сути коммента — вы заблуждаетесь.
            Во-первых, git — это кучка из скриптов на bash, perl и С.
            Во-вторых, узкие места в mercurial уже сто лет как переписаны на C.
            • –2
              Вы какой git используете?

              Под Windows есть git.exe…
              • +3
                Под Windows есть git.exe…
                …который тупо проксирует переданные параметры скрипту по имени git-[имякоманды]. В Debian эти скрипты заботливо собраны в каталоге /usr/lib/git-core/, под виндами не знаю, где их искать, но уверен на 90%, что они тоже где-то в недрах \Program Files имеются. А в старых версиях git эти скрипты выкакивались прямо в /bin всей толпой в ~140 штук.
                • –2
                  На самом деле под Windows все наоборот.

                  Команда git-add проксирует add параметр в git.exe…
                  • 0
                    Возможно, я под виндами не работаю.
                    Под Linux же бинарники в указанном мной каталоге вроде как являются по большей части хардлинками, т.к. у них совпадает размер. Похоже, что я всё-таки неправ насчёт пачки скриптов. Git — это один большой скрипт ;)
                    • –5
                      Один большой бинарник, написанный на C.
                      А вот Mercurial — написан на Python, поэтому и тормозит
                      • +5
                        ппц, граждане.
                        Вы сами-то задумайтесь, чем меряетесь — скоростью коммитов.
                        Это доли процента от общего времени работы с кодом.
                        • 0
                          Ребе, я ему сразу сказал, что бенчмарк нерелевантен.
      • 0
        Похоже хабраэффект. У меня не открывается.
        • 0
          Да нет, все нормально. Да потом тема не та, что бы хост со ссылкой в комментарии завалить :)
          • 0
            Тем не менее — у меня не отрывается. Хотя хост пингуется исправно.
    • +1
      Они на столько схожи, что с помощью плагинов вы можете свободно работать из hg в git и наоборот. При этом иметь все плюшки друг-друга(лукавлю, почти все)
      • 0
        а как это «наоборот»? По-моему, git умеет только конвертировать репозитории mercurial
    • +6
      Тор Норби в одном из последних подкастов делился своим опытом перехода с HG (когда он был в Оракл) на Git (теперь он работает в Гугле). Считает киллер-фичей Гита возможность склеить несколько патчей в один коммит. Например, работаете вы над каким-то таском, добились какого-то рабочего состояния и решили выложить изменения. А потом оказалось, что код грязноват, мб где-то идет отклонение от style-guides или какие-то debug выводы остались. Все прочистили, сделали красиво и опять закоммитили. Так вот, в Git можно взять эти два чейнджсета и объединить в один — как будто код с самого начала писался чистенько и по стандартам. В результате, говорит он, все чейнджсеты оказываются по делу, что особенно важно в большом проекте, когда их в целом очень много.
      • 0
        Спасибо, этой особенности не знал. А фича действительно здоровская, надо будет почитать.
      • +6
        mq?
        • +4
          спасибо, ответили за меня :)
          Товарищи, кому не хватает стандартного функционала Hg — пользуйтесь его екстеншенами (идут в пакете с Hg). Лично для себя я нашёл полезными mq, transplant и rebase.
      • 0
        спасибо, интерсно!
        в hg мне переодически приходится делать hg rollback и думать перед тем как запушить
      • +2
        В hg этот функционал реализован расширением histedit. Это если не принимать во внимание искоробочные Mercurial Patch Queues.
      • 0
        Если вышеприведенные способы оказались «большими» и не изящными, можно попробовать расширение
        mercurial.selenic.com/wiki/CollapseExtension, которое делает только и именно то, что вы описали.
  • +4
    Последний абзац самый мотивирующий=)
  • 0
    аааа! Джоель, ты гениален! Что бы не пришлось изменять в команде, ты это уже попробовал и написал об этом статью.
    Переводчику большой респект! Ждем продолжения.
    • +2
      Спасибо! С переводом второй части планирую сильно не затягивать.
  • 0
    Спасибо, заставили задуматься
  • 0
    Интересно, в чем отличие от git
    • 0
      • 0
        кажется ссылка указывает на эту же страницу… или я не туда жму? :)
        • 0
          Именно) Она указывает на комментарий выше, в котором ссылка туда куда нужно)
          • 0
            О! Проворонил :) Неприменно положу в закладки
    • 0
      Слышал мнение, что git — он больше linux-way, а hg удобнее при разработке под виндой. Насколько правда — не знаю, мопед не мой.
      • +1
        Наверное потому что git написан тем же человеком что писал написал linux, нет?

        C git под виндовс удобно работать через клиенты, например через SmartGIT и cygwin не нужен.
        • +2
          hg, к слову, тоже целенаправленно писался как замена BitKeeper для Linux kernel.
  • –1
    Круть! Спасибо за перевод! С удовольствием прочитал бы оригинал! Последний обзац заставил меня попробовать Mercurial. В компании мы исспользуем SVN, но всегда хочеться попробовать что-то новенькое. Эта статья дала толчёк к новым изменениям!
  • +1
    Отличная статья. Я тоже потихоньку переползаю на DCVS вроде GIT. Но мне кажется, что все же некоторые страсти вроде
    И почти в каждой команде мне сказали, что они поклялись «больше никогда» и отказались от веток. И теперь они делают так: каждая новая фича в большом #ifdef блоке.
    притянуты за уши. Что может быть хуже ifdef для новых фич в проектах? :)
  • 0
    Эх… А мне ведь осталось совсем маленько, чтобы перевод закончить. Спасибо, что сэкономили моё время :)

    Кстати, сегодня как раз смотрел лекцию Торвальдса с переводом, где он рассказывает про свой Git (есть топик на Хабре). Идеи у него практически те же, что и у разработчиков Меркуриала. И он довольно неплохо обосновывает, что децентрализация гораздо лучше.
  • 0
    Упрёки к svn актуальны к древним версиям. В 1.6 уже более-менее приличные ветки. Единственное что меня не устраивает в svn это подключение к интернету для создания ветки.
  • 0
    Чем hg лучше git'а?
    • 0
    • +2
      — Простым, предсказуемым и интуитивно понятным интерфейсом.
      — Как следствие, временем освоения
      — Наличием туевой хучи расширений (а не обвязок, как в git) и возможности писать эти расширения
      — Прозрачной поддержкой репозиториев git (расширение hg-git)
      — Вебмордой искаропки
      навскидку пока всё.
      • 0
        перевожу svn repo на git. процесс — хоть плачь.
        • 0
          Не, без поллитры приличного опыта использования Git взять и переехать практически невозможно.
  • 0
    Mercurial действительно хорош и довольно прост в использовании. Когда переходили на него, тоже поначалу работали как с SVN, но потом образумились :)
  • 0
    Написано ясно и понятно, я сам только Clear Case и SVN использовал, много нового для себя открыл
  • –9
    много воды и рекламы меркурал.
    • +1
      На самом деле таким способом Джоел рекламирует свой Килн www.fogcreek.com/kiln/
    • 0
      ну, Ъ-мужики сразу бы прочитали весь mercurial wiki и сказали своё суровое «одобряю»
    • +5
      все лучше чем размусоливание темы.РФ и нытье про сотовых операторов…
  • 0
    А что будет в меркуриал, если я изменил что-то в коде функции, а мой коллега удалил её и внёс изменения в центральный репозиторий первым? Функция исчезнет? И как оповещается локальные ветки об изменениях в центральном репозитории? В ручную, через пул чэньджсет?
    • +1
      вас известят, я полагаю, и попросят сделать pull. Если ваши изменения имеют более позднюю версию то произойдет мерж (соответственно функция вернется все будет ок). Если нет то вам предложат сделать stash после чего вы обновите локальную версию и сможите закоммитить изменения которые вы stashнули. Это не о меркуриал это о гит, но подозреваю, что механизм и там и там одинаковый.
      • +1
        ЗЫ: Уточню известят при попытке pull'a. А вообще я придерживаюсь концепции девелоперских бранчей.
        • 0
          Т.е. разбить изменения на не пересекающиюся множества? Один работает над одним, другой над другим функционалом? Меня как раз интересовал вопрос об одновременном редактировании документа. По Вашим словам если даже я сначала что-то изменил, а потом это удалили (не зная о моих изменениях) то всё восстановится?
          • 0
            Отвечу на последний вопрос. Вам предложат смержить две ветки. Во время этого процесса вы сможете сделать с кодом всё что вам нужно. Оставить другой код, оставить ваш с изменениями, удалить оба и т.п.
          • 0
            >>Т.е. разбить изменения на не пересекающиюся множества?
            Да именно так, но это скорее некое рудиментарное мышление оставшееся от svn. Хотя в git оно вполне применимо, и удобно.
            >>По Вашим словам если даже я сначала что-то изменил, а потом это удалили (не зная о моих изменениях) то всё восстановится?
            Именно так, опять же говоря о git. Система даст потерять ваши изменения только в случае если вы их сознательно потрете. В случае если вы пересечетесь с другим разработчиком, то кроме как сделать stash вам ничего не останется (ну или радикально потереть локальную версию и сделать новый клон). Ну и естественно если иземенения, которые вы сделали, невалидны, out-of-date(список продолжить), на человеческои уровне, можно просто потереть свои изменения из stash. Как-то так. я не очень владею навыком что-то объяснять признаюсь, мне больше удается показывать все на рисунках. Но надеюсь вам это поможет )
            • 0
              Да, спасибо. То есть от ручного мерджа мы никуда не уходим, просто он реже встречается. Но так ведь и в СВН можно разграничить задачи изменения функционала до непересекающихся множеств. Если честно, я предпологал, что чэньджсет это дельта в смысле ленивых вычислений, тогда в любой момент мы можем вычислить конечный вариант документа, применяя цепочку последовательных дельт к исходному файлу, а цепочка эта может пополнятся как с конца, так и изнутри, т.е. могут вносится изменения, которые с точки зрения центральной ветки (глобальный коммит) произошли позже, но с точки зрения локальной ветки (локальный коммит) они предшествуют некоторым изменениям уже внесённым в центральную ветку. Т.е. ход времени в локальных ветках синхронизируется по центральной ветке.
              • +1
                Тут поспорить не могу, в свн по возможностям в принципе не ограничен. Но дело в инструменте. Если в свн возможность удобного удачного мержа средствами самой системы очень ограничена, то тут сама система предлагает надежный и удобный механизм мержа, по сути механизм, stash это, то что вы описали только «с разрешения пользователя».
                Позволю себе продемострировать, как это будет выглядеть в коммандах:
                $ git commit #коммит в ваш репозиторий
                $ git push #push в «главный» репозиторий который уже поменялся

                $ git stash save#Копируем сделаные вами изменения
                $ git pull
                $ git stash list
                • 0
                  прошу прощения парсер съел «теги»
                  $ git commit #коммит в ваш репозиторий
                  $ git push #push в «главный» репозиторий который уже поменялся
                  //тут сообщение о том что репозиторий поменялся
                  $ git stash save#Копируем сделаные вами изменения
                  $ git pull
                  $ git stash list
                  //тут список ваших stash'ей
                  $ git stash apply [ stash_id ]
                  $ git push
        • 0
          в Hg при попытке pull никаких извещений не будет. Конфликт изменений обнаружится во время мержа своего коммита в текущий бренч. Соответсвенно выскочит 3-way merger для решения конфликта, а там уже вы сами решаете, восстановить удаленную функцию или нет.
          • 0
            А если коммит уже произошел, а pull перед этим не был сделан?
            • 0
              в локальном репозитории коммит создаёт новую неименованную ветку, тоесть после pull, серия коммитов еще не отправленных на центральный репозиторий, будет выглядеть как отдельная ветка. Вашей задачей перед выполнением push смержить ветку своих коммитов в основную ветку центрального репозитория.
              • 0
                ну значит мне больше нравится git )
                • 0
                  и не забудьте, что hg pull == git fetch
                  • 0
                    Механизм мне в любом случае показался маленько запутаным, и неочевидным, но это наверное всеже дело привычки )
                    А вот насчет вашего высказывания объясните пожалуйста о чем вы вели речь?
                    fetch это обыкновенная загрузка, без каких либо мержей и т.п., так сказать «тупо качаем файлики», то что обрисовал выше товарищ AdvanTiSS намного умнее этого действа.
                    • +1
                      hg pull тоже ничего не мергает, поэтому сравнивать его с git pull некорректно.
                      и да, имя ветки в hg содержится в метаданных changesetа, поэтому сравнивать ветки в hg и git тоже не совсем корректно.
                      • 0
                        Вот теперь алгоритм стал понятнее, спасибо )
                • 0
                  чтобы не плодить ветки можно сделать hg pull --rebase
            • 0
              тогда при pull вам скажут, что у репозитория появились новые головы (heads) и предложат их смергать
  • 0
    уже некоторое время пользуюсь bitbucket.org, это просто мегаудобно! для обновления продакш-сервера достаточно сделать hg pull && hg update и все! но для этого хостинг должен предоставлять ssh (если это не VPS)…

    а всякую мишуру типа обновления, переиндексации и прочих телодвижений можно вешать на триггеры
    • 0
      hg pull --update
      или hg fetch
  • –1
    > Если, для примера, я немного изменил какую-то функцию и перенес ее куда-то, то Subversion на самом деле не помнит этого. Так что когда дело дойдет до слияния, она просто может решить, что в коде из ниоткуда появилась новая функция. В то же время, Mercurial запомнит: функция изменилась, функция переместилась. Это значит, что если вы тоже поменяли эту функцию, то вероятность того, что Mercurial успешно проведет слияние наших изменений, гораздо больше.

    Или я пример неправильно понял, или одно из двух, но при попытке его воспроизвести ничего кроме предложения вручную поправить конфликт при мерже не наблюдаю.
  • 0
    Последняя капля в пользу Hg. Спасибо за обзор и сравнение, отличная статья.
  • +2
    > Subversion, по сути, система контроля изменений для файлов, а в Mercurial контроль изменений применяется ко всему каталогу, включая все подкаталоги.

    Это утверждение может создать ложное впечатление.

    На самом деле, Mercurial — система контроля изменений «только для файлов», она не знает что такое каталоги. Поэтому, например, вы не сможете закоммитить пустой каталог (но если очень надо, можно создать в нём пустой файл, и закоммитить). Но, при этом, выполнение операции в подкаталогах будет выполняться будто бы мы делаем это из корневого каталога репозитория. Каталог .hg содержится только в корне репозитория.

    В Subversion, напротив, каталоги (в том числе и пустые) прекрасно коммитятся. Операции в подкаталогах же производятся «локально», поэтому, например, закоммитив какой-либо подкаталог, вы получите разные ревизии для него, и для корневого, то есть репозиторий можно привести в некоторое «противоречивое» состояние когда разные каталоги имеют разные ревизии. Получается, грубо, что каждый каталог — это репозиторий. В каждом каталоге есть .svn (или _svn).
    • 0
      можно вопрос? в чем идеалогический смысл коммитить пустые каталоги? Вообще зачем они нужны в репозитории? Если вы собираетесь в них что-то положить, но этого пока нет, то для коммандной работы я думаю будет полезно например положить в них файлик с описание, а что же там должно лежать.
      То что вы привели как аргумент, это уродливый брат веток в mercurial и git.
      • 0
        Лично мне вообще ни зачем не надо, и я придерживаюсь вашей же точки зрения, здесь это как пример доказывающий отношения Mercurial к каталогам.
      • 0
        И поясните, пожалуйста, последнее предложение, никак не соображу, к чему это вы.
        • 0
          Ну в целом плодить множество каталогов как «отдельные репозитории», это то что легло в основу бранчей. Только вот если «бранчеваться» в svn невыносимо неудобно, долго и последующие действия над нимим невозоможно качественно и быстро выполнить без сторонних программ, то в git и (как я сегодня узнал ;) ) в mercurial это делается легко и не принужденно. Ну собственно вот )
          • 0
            Это не был не аргумент, а описание несовершества Subversion =) Я влюблён в Mercurial и очень рад что уже примерно как год сбежал на него с SVN.
            • 0
              Извиняюсь если это выглядело как «наезд») просто не понял зачем вы пытались привести некий костыль(рудимент возможно) свн, как недостаток git и mercurial ) Теперь понял что это просто акцент на еще одном из принципиальных различий )
      • 0
        каталоги — это те же файлы, только содержимое у них не текст, а другие файлы.

        В чем идеологический смысл коммитить одни файлы, но не коммитить другие?

        Вспомните, для чего нужен .hgignore (.gitignore).
        • 0
          Ну если учитывать что в git файлы смысловой нагрузки тоже не несут, все заложено в changeset то смысла в пустых файлах тоже нет ;) Стрельнуло пока писал ЗЫ, для бинарных файлов, понятие файла всеже имеет смысл, делать changeset для них маленько не возможно )

          Насчет gitignore тут как бы их роль очевидна, но связи я не улавливаю объясните )

          И маленькое лирическое отступление аля ЗЫ: Мне вообще нравится это пост, я сегодня немало интересного и новго узнал )
        • 0
          Цитата из чудо-книги «Mercurial: The Definitive Guide»:
          Empty directories are rarely useful, and there are unintrusive workarounds that you can use to achieve an appropriate effect.
          The developers of Mercurial thus felt that the complexity that would be required to manage empty directories was not
          worth the limited benefit this feature would bring.
      • +2
        Элементарные примеры.
        1.
        У меня есть болванка сайта. Это фреймворк с php-классами, но без вёрстки, без картинок и без всего такого что создаётся под проект. При этом, в болванке есть готовая структура папок на будущее:
        /template/
        /template/images/
        /template/images/icons/
        /template/images/buttons/
        /template/images/bg/
        /template/css/
        /template/js/


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

        2.
        У меня есть папка /logs/ и я добавляю её в репозиторий. Но, так как логи пишутся при каждом запуске скрипта, я делаю для этой папки «ignore *» — что бы не было конфликтов.
        Я бы мог вообще не добавлять эту папку под контроль, но тогда остальные программисты её не получат. А если не будет пустой папки, то PHP будет сильно ругаться на fopen('logs/sql.log.txt', 'a+');
        • 0
          гм а не проще создать один файлик вот с таким содержанием:
          /template/
          /template/images/
          /template/images/icons/
          /template/images/buttons/
          /template/images/bg/
          /template/css/
          /template/js/

          ?))))

          Насчет второго как бы изначально инициализируется пустой лог, а потом ему ставится игнор. Так что тоже не аргумент. И это не костыли, а логичное решение…
          • +1
            1. Совсем не проще.

            Абсолютно логичное решение, очевидное для всех — это коммитить папки. Тем более, что папка — это самый обычный файл.
  • +1
    с моей точки зрения, на этом сайте лучше всего разъяснена разница между гитом и меркуриалом
    gitvsmercurial.com/
    • 0
      вот это пятнично весьма!)))
      Справа кстати Qt еще;)
      • 0
        черт вроде права давно получил, а право с лево до сих пор путаю ) в общем Qt под git'ом )
    • +1
      > юзайте то что ВАМ нравится и не обращайте внимание на то что говорят в интернете.

      Тогда нафига вообще Хабр читать? Сидели бы на SVN-е и продолжали бы сидеть.
  • 0
    Примерно подобной статьи я сидел и ждал. Теперь, пожалуй, подвигаюсь немножко и попробую Hg :)
  • 0
    Вот читало бы моё начальство такие статьи и делало выводы, а то мы еще сидим на CVS, хотя когда один работаешь над проектом, то еще ничего.
    • 0
      Ладно хоть еще билды на дискетках по пятницам собирать не приходится))
  • +2
    И всё-таки не пойму, как не на картинках или искусственных демках, а по жизни работает hg/git (организационно, как я понял, они друг от друга мало отличаются).

    Вот есть два разработчика (каждый со своим компом), есть тестовый сервер (пускай владелец — тестер), на который бы хотелось автоматом деплоить приложение (ЯП — интерпретируемый, компиляции/сборки не нужно, миграции БД пока за рамками оставим, с файлами бы разобраться) при коммите в ветку test, и боевой сервер (пускай владелец тимлид) — аналогично на него деплоить ветку trunk(production/...). Надо заводить 4 (2 девелоперские машины, тестовый и боевой сервера) локальных репозитория с 4 ветками (dev1, dev2, test, production) в каждом и постоянно их как-то (ручками, хроном, сигналы какие-то друг другу посылают?) синхронизировать друг с другом? Кто выступает инициатором синхронизации — тот, кто делает коммит, требующий синхронизации (то есть распространяет свой коммит на 3 локальных репозитория без их владельцев согласия), или тот, кто хочет свой локальный синхронизировать с остальными (то есть для деплоя на тест нужно будет логиниться на тестовом сервере и опрашивать девелоперские репозитории на предмет изменений, а для деплоя на боевой логиниться на нём и опрашивать тестовый)? Как обеспечивается синхронизация с внешними репозиториями (либы, фреймворки, cms и т. п.)? С SVN всё понятно: закоммитил — всем доступно (если с правами не играть) и об изменениях узнают при очередном чекауте, хуки повесил — отдеплоилось при коммите (с одного заранее известного хоста), а тут? Кричать на весь офис (или в чат) «Я замержил свой патч на тест у себя — синхронизируйтесь со мной и тестируйте» или «О, либа обновилась, все качаем в каждую ветку кроме продакшн и ищем баги дружно!»?

    Может кто-нибудь ткнёт пальцем в статью/пост, где описана схема реальной работы (желательно на русском и/или со множеством картинок, а то с залогами всякими английскими проблема)? habrahabr.ru/blogs/Git/106912/ читал, но, как я понял, это не тру-гит вэй, т. к. всё-таки централизованно выходит, да и подробностей маловато. Или я просто несколько опережаю события и в следующих частях всё будет?

    • +2
      Во-первых, я бы деплоил обновки как на staging, так и на production с помощью capistrano. Для проектов на базе symfony есть capifony — феноменально полезный addon (kudos to everzet).
      Надо заводить 4 (2 девелоперские машины, тестовый и боевой сервера) локальных репозитория с 4 ветками (dev1, dev2, test, production) в каждом и постоянно их как-то (ручками, хроном, сигналы какие-то друг другу посылают?) синхронизировать друг с другом?
      Хм, по факту да, в случае DVCS каждая якобы «рабочая копия» фактически является репозиторием. Но это ничего не меняет — мы точно так же можем использовать централизованную модель разработки — поднимаем репозиторий на серваке в локалке/BitBucket/GitHub и пинаем изменения уже туда. Ну то есть чтобы поделиться обновками с коллегами, нужно сказать не commit, а push. И всего-то. Чтобы рассылать уведомления об обновках, можно наваять post-push хук (или в настройках BitBucket указать email рассылки например).
      Как обеспечивается синхронизация с внешними репозиториями (либы, фреймворки, cms и т. п.)?
      Mercurial: subrepositories (поддерживается в т.ч. и svn); Git: git help submodule
      С SVN всё понятно: закоммитил — всем доступно (если с правами не играть) и об изменениях узнают при очередном чекауте, хуки повесил — отдеплоилось при коммите (с одного заранее известного хоста), а тут?
      Всё не менее понятно: выпнул — всем доступно и об изменениях узнают при очередном pullе, хуки повесил — отдеплоилось при pushе (с одного заранее известного хоста).
  • +3
    Mercurial — первая система контроля версии, которую я начал использовать. Я полностью доволен.
    • +1
      Вы везунчик.
      Мне, к примеру, пришлось пройти и через MS VSS, и через SVN, и через ClearCase, и через P4.
      • +1
        Про две из четырех я даже не слышал. Действительно — повезло.
        • 0
          Одна из них, подозеваю, P4 (Perforce), а вторая какая? VSS или CC?
          • 0
            CC
            • 0
              Тогда Вы вдойне везунчик! :)
  • –1
    «И Майк расслабится и поделится косячком с практикантами, и наступит весна, и молодежь из соседнего колледжа сменит пуховики на коротенькие надорванные футболки, и жизнь будет хороша.»

    Если этот Джоэль Спольски, автор пособия, наркоман, любящий заглядывать под коротенькие надорванные футболки молодёжи, то хотя бы на русский можно было это не переводить.
    • 0
      и здесь эти долбаные ханжи
  • 0
    Перечитывал тут статью и проассоциировал вашего Джейкоба с одноименным героем лоста)
  • 0
    Вот этот момент смутил в статье.

    Когда нам нужно сделать слияние, Subversion смотрит на обе ревизии — мой измененный код и ваш измененный код — и пытается угадать, как слепить их вместе в один большой страшный бардак. Обычно Subversion это не удается, и получаются длинные списки конфликтов («merge conflicts»), которые на самом деле не конфликты, а просто места, в которых система не смогла разобраться в наших изменениях.

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

    Если, для примера, я немного изменил какую-то функцию и перенес ее куда-то, то Subversion на самом деле не помнит этого. Так что когда дело дойдет до слияния, она просто может решить, что в коде из ниоткуда появилась новая функция. В то же время, Mercurial запомнит: функция изменилась, функция переместилась. Это значит, что если вы тоже поменяли эту функцию, то вероятность того, что Mercurial успешно проведет слияние наших изменений, гораздо больше.

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

    Если все это кажется вам немного запутанным — не переживайте. По мере чтения этого пособия все обретет ясный смысл. В данный момент самое главное, что вам нужно знать: из-за того, что Mercurial оперирует наборами изменений, а не ревизиями, слияние кода в Mercurial работает гораздо лучше, чем в Subversion.


    Какая разница — changeset или слепок файлов система хранит? В любом случае если я удаляю функцию из одного файла, вставляю в другой.
  • +1
    Спасибо за перевод. В целом статья очень полезна. )

    Только вот этот момент смутил:

    Когда нам нужно сделать слияние, Subversion смотрит на обе ревизии — мой измененный код и ваш измененный код — и пытается угадать, как слепить их вместе в один большой страшный бардак. Обычно Subversion это не удается, и получаются длинные списки конфликтов («merge conflicts»), которые на самом деле не конфликты, а просто места, в которых система не смогла разобраться в наших изменениях.

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

    Если, для примера, я немного изменил какую-то функцию и перенес ее куда-то, то Subversion на самом деле не помнит этого. Так что когда дело дойдет до слияния, она просто может решить, что в коде из ниоткуда появилась новая функция. В то же время, Mercurial запомнит: функция изменилась, функция переместилась. Это значит, что если вы тоже поменяли эту функцию, то вероятность того, что Mercurial успешно проведет слияние наших изменений, гораздо больше.

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

    Если все это кажется вам немного запутанным — не переживайте. По мере чтения этого пособия все обретет ясный смысл. В данный момент самое главное, что вам нужно знать: из-за того, что Mercurial оперирует наборами изменений, а не ревизиями, слияние кода в Mercurial работает гораздо лучше, чем в Subversion.


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

    Какая разница — changeset или слепок файлов система хранит? Откуда у меркуриала больше информации?

    В любом случае если я
    в ветке А — удаляю функцию из одного файла, вставляю в другой.
    в ветке Б — меняю тело функции на пару строк

    Ниодна система контроля версий этого сама не смерджит. Мне кажется ближе к истине вот это programmers.stackexchange.com/a/129926

    Subversion, Mercurial, and Git all track repository-wide snapshots of the project. Calling them versions, revisions, or changesets makes no difference. They are all logically atomic snapshots of a set of files.

    The size of your commits makes no difference when it comes to merging. All three systems merge with the standard three-way merge algorithm and the inputs to that algorithm are

    greatest common ancestor version
    version on one branch
    version on other branch
    It doesn't matter how the two branch versions were created. You can have used 1000 small commits since the ancestor version, or you can have used 1 commit. All that matters is the final version of the files. (Yes, this is surprising! Yes, lots of DVCS guides get this horribly wrong.)



    The real reason Git and Mercurial are better at merging than Subversion is a matter of implementation. There are rename conflicts that Subversion simply cannot handle even thought it's clear what the correct answer is. Mercurial and Git handles those easily. But there's no reason why Subversion couldn't handle those as well — being centralized is certainly not the reason.
    • 0
      Вполне возможно, что все так и есть.
      • 0
        Может имеет смысл вставить ссылку на коммент внутри статьи? :)
        • 0
          Думаю, нет. Потому что это перевод.

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