Изменения

Перейти к: навигация, поиск

Сравнение DVCS - несколько задач

26 685 байтов добавлено, 15:47, 2 августа 2010
м
Нет описания правки
Данная статья является очередным сравнением популярных [[wikipedia:Distributed revision control|DVCS]] — [http://selenic.com/mercurial/ Mercurial], [http://git-scm.com/ Git] и [http://bazaar-vcs.org/ Bazaar], с точки зрения нескольких нетривиальных задач. Ссылка: [http://yourcmc.ru/DVCS_YAC http://yourcmc.ru/DVCS_YAC] («Yet Another Comparison»). Хотите лаконичный ответ в стиле «ИМХО» на вопрос — кого выбрать из трёх? Ну пожалуйста. Выбирайте Mercurial. А не Git (безумный конгломерат) и не Bazaar (пионерское поделие, унаследованное от Arch’а).
== Работа с SVN (миграция и синхронизация) ==
Что ещё любопытно — с Subversion-репозиториями DVCS работают, как правило, быстрее самого Subversion, и быстрее всех работает '''Bazaar'''. То есть, в принципе, можно вообще жить с Subversion-сервером и DVCS-клиентом (если, конечно мириться с постоянными слияниями и rebase’ами).
Во всех трёх DVCS при работе с Subversion есть следующее ограничение: невозможно связывать один и тот же репозиторий с несколькими Subversion-источниками — ни в пределах разных веток, ни в пределах разных каталогов. Mercurial честно говорит «repository unrelated», Bazaar — «branches have no common ancestor», Git пытается что-то родить, но запутывается в одинаковых коммитах, имеющих несколько SVN-родителей. А ведь было бы неплохо иметь такие возможности… === Mercurial === '''Mercurial''': почти отлично! Есть несколько расширений — (5-), есть 3 расширения различной степени глюкавости — [http://mercurial.selenic.com/wiki/HgSubversion hgsubversion], [http://pypi.python.org/pypi/hgsvn hgsvn], [http://mercurial.selenic.com/wiki/ConvertExtension convert], из которых позволяющих работать с Subversion тем или иным образом, и не совместимых друг с другом.  Самое вменяемое из них — этих расширений — '''hgsubversion''', и хотя и заявлено, что оно ещё сыроесыровато, иразработка ведётся активно, к сожалениюв мэйллисте постоянно происходит некая жизнь, не распространяется вместе а автор отзывчив. Вместе с Mercurial’омоно не распространяется, нужно ставить отдельно. Тестировал я ревизию 500 из http://bitbucket.org/durin42/hgsubversion. Имеет фактически весь основной необходимый функционал — можно делать и <tt>push</tt>, и <tt>pull</tt> в/из Subversion, можно клонировать SVN-репозиторий с сохранением веток и меток (правда, обязательно стандартное их расположение в корневых поддиректориях <tt>/trunk</tt>, <tt>/branches</tt>, <tt>/tags</tt>), эти два метода совместимы, <tt>rebase</tt> также работает, а граф ветвлений сохраняется. Очень крут тот факт, что ветка, которая создавалась неполным копированием <tt>trunk</tt>'а, то есть, копированием некоторых его поддиректорий, успешно подцепилась в нужное место графа ветвлений. Ни Bazaar, ни Git этого не смогли. Поддержки svn:mergeinfo пока что нет, хотя она близится. Минус расширения заключается в сырости — за время тестирования я нашёл уже несколько неприятных багов:* <tt>push</tt> из Mercurial-клона репозитория без веток и меток (имеющего вид просто одного каталога) в Subversion не работал вообще — [http://groups.google.com/group/hgsubversion/browse_thread/thread/3749eb3cbf007855 обсуждение в группе hgsubversion]. К счастью, меня пропёрло, я потратил час времени и баг этот пофиксил собственноручно. [[hgsubversion-fix-for-singledir-repo.diff|Фикс]] очень простой, на две строчки, и он уже находится в репозитории в виде ревизии r501 — за отзывчивость автору зачёт.* <s>Не работает клонирование репозиториев по протоколу [http://svnbook.red-bean.com/en/1.0/ch06s03.html svnserve] (<tt>svn://host:port/url</tt>). Очень неприятно, особенно, если вы предпочитаете именно <tt>svnserve</tt> по причине его производительности.</s> Уже давно работает.* Течёт память, что при клонировании '''толстых''' SVN-репозиториев (например, [http://svn.wikimedia.org/svnroot/mediawiki/ репозитория MediaWiki]) приводит к ошибкам <tt>Abort: out of memory</tt>, то есть нехватки памяти. Обходится методом клонирования репозитория по частям, делая <tt>hg init</tt>, а потом несколько <tt>hg pull</tt> до победного конца. Причина в дырявости [http://www.swig.org/ SWIG] SVN Python-библиотеки. Забавно, что аналогичная [http://www.swig.org/ SWIG] Perl-библиотека такой текучестью, видимо, не страдает, так как Git этот репозиторий глотал (причём по 10 раз за раз) и не давился. ''Perl, говорите, течёт? Ну хи-хи, хи-хи.'' Кстати, Bazaar течёт точно так же, как <tt>hgsubversion</tt>.* На ревизии 43380 MediaWiki <tt>hgsubversion</tt> свалился с ошибкой <tt>abort: phase3/includes/ConfigurationCache.php@a1335975fba6: not found in manifest!</tt>. [http://groups.google.com/group/hgsubversion/browse_thread/thread/2a2ae0aa680054ec обсуждение в группе hgsubversion]. Причина, вероятно, кроется где-то в районе обработки перемещений каталогов Subversion. Я обошёл данный баг убиением части файла <tt>.hg/svn/rev_map</tt> (можно было и весь убить) и перезапуском <tt>hg pull</tt>. Однако в итоге появилось две ветки вместо одной: <tt>on_wiki-configuration</tt> и <tt>on_wiki-configuration/phase3</tt> (подкаталог ветки…) Итог клонирования MediaWiki-репозитория: успешно с небольшими танцами с бубном — склонировал за несколько перезапусков <tt>pull</tt>'а и с уборкой <tt>rev_map</tt> в середине, все ветки на месте, только одна, перемещённая потом в подкаталог себя, продублировалась: «<tt>on-wiki_configuration</tt>» и «<tt>on-wiki_configuration/phase3</tt>». Репозиторий (то есть директория <tt>.hg</tt>) занимает на диске '''1.63 Гб'''.
Остальные два экстенжна «нинужны»: <tt>hgsvn</tt> — нечто более старое, работает сбоку от общего механизма, тоже позволяет делать push и pull, но не клонирует весь репозиторий, а только извлекает (checkout’ит) последнюю версию, чтобы далее можно было использовать Subversion и Mercurial вместе. Ну и конечно, оно не совместимо с <tt>hgsubversion</tt>. <tt>convert</tt> же предназначен для конвертации истории проекта из нескольких различных систем контроля версий в Mercurial, ни черта не совместим ни с <tt>hgsvn</tt>, ни с <tt>hgsubversion</tt> и не сохраняет граф ветвлений. Зато, правда, поддерживает возможность использования других имён поддиректорий <tt>trunk/branches/tags</tt>.
=== Git === '''Git''': очень хорошо отлично (5-)! <tt>[http://git-svn.yhbt.net/ git-svn]</tt> встроен в git и умеет всё, что нужно: клонирование, синхронизация (<tt>fetch</tt>, <tt>pull</tt> или <tt>merge</tt>), фиксация изменений в Subversion-репозиториях (<tt>dcommit</tt>) и <tt>rebase</tt> работают с сохранением веток и меток, причём стандартная схема их именования <tt>trunk/branches/tags</tt> не является обязательной. Ветки SVN импортируются как [http://www.gitready.com/beginner/2009/03/09/remote-tracking-branches.html Remote Tracking Branches], что тоже удобно — можно . Можно начинать историю ветки в git’е не с сотворения миров, а с любого момента. Также <tt>git-svn</tt> поддерживает подключаемые внешние репозитории Subversion (т. н. [http://svnbook.red-bean.com/en/1.0/ch07s03.html Externals]). Граф ветвлений сохраняется, хоть и не так круто, как в Mercurial’е. В общем, можно сказать, что функционал фактически полон.<tt>git svn fetch</tt> успешно возобновляет операцию клонирование в случае её падения посредине. А теперь поговорим о неприятном: полное клонирование [http://svn.wikimedia.org/ SVN-репозитория MediaWiki] заняло более 3 дней, хотя должно по логике занимать часов 6-8. Причина в том, что Git время от времени не понимает, откуда ответвилась ветка, лезет в глубокую историю и начинает сканировать по новой уже просканированные ревизии. Таким образом, некоторые (а конкректно — ветвлённые не из самого trunk’а, а из его подпапок) ветки не получаются связанными с историей trunk’а, старые ревизии для них дублируются. Справедливости ради надо отметить, что для двух таких веток старая история объединяется, а физически никаких дубликатов не хранится. Вообще в итоге Git-клон репозитория MediaWiki (директория .git) занял всего '''845 Мб'''. Кроме того, в процессе клонирования память '''не текла вообще''', на всё про всё уходило мегабайт 80 памяти. Кроме того, как всегда с Git’ом, есть различные нетривиальности, что-то бывает нужно настроить (''гитара настроена? нас двое, на! играй, на!''), синтаксис не совмещён с обычными командами Git — то есть например для синхронизации копии с Subversion нужно сказать не <tt>git pull</tt>, а <tt>git svn fetch</tt>. === Bazaar ===
'''Bazaar''': хорошо. Можно импортировать репозиторий командами <tt>svn-import</tt> или <tt>branch</tt>, можно делать <tt>push</tt> и <tt>pull</tt> в/из Subversion. При импорте можно сохранить все ветки и метки в одном хранилище (если использовать [http://bazaar-vcs.org/SharedRepositoryTutorial Shared Repository]), для этого также требуются стандартные названия <tt>trunk/branches/tags</tt>. Граф ветвлений Subversion сохраняется, но также не отражает копирования подпапок. Также существует несколько других расширений для импорта Subversion в Bazaar, но они хуже.
И всё было бы замечательноТест на клонирование репозитория MediaWiki прошёл почти без проблем, но почему-то вместо 59589 ревизий копировал 85567 ревизий, то есть одна очень неприятная проблемаоткуда-то придумал лишних 25978. Причём Возможно, это были ветки — корректного присоединения их истории к <tt>trunk</tt>'у обнаружено после клонирования '''не было вообще''' (!). Причина, скорее всего, в том, что ветки там в основном не совсем честные (как уже было упомянуто в секции про '''Git''') — они создавались не командой <tt>svn cp trunk branches/ветка</tt>, а создавался каталог ветки и в него копировались каталоги <tt>phase3</tt> и <tt>extensions</tt> из <tt>trunk</tt>’а. В итоге изменения, происходившие «до» создания таких «нечестных» веток, в самих ветках вообще не отражены. Память течёт точно так же, как и Mercurial’е и, очевидно, по той же причине (SWIG), и перезапуски процесса клонирования по причине ухода машины в глубокий своп также были необходимы. После клонирования репозиторий изначально занимал аж 16 Гб, однако при ближайшем рассмотрении стало ясно, что большую часть этого пространства занимали каталоги <tt>obsolete_packs</tt> и <tt>upload</tt> со старыми упакованными данными репозитория и некими временными файлами соответственно. Такая же ситуация осталась и после вызова <tt>bzr pack</tt>, о чём есть целый баг: [https://bugs.launchpad.net/bzr/+bug/304320 Bug 304320 — bzr pack should (optionally?) delete obsolete packs]. Все эти лишние данные, по-видимому, можно смело удалить ручками — и обнаружить, что репозиторий занимает '''925 Мб''', то есть, лишь ненамного больше, чем в случае Git, и примерно в 1.75 раза меньше, чем в Mercurial’е. Правда, по ощущению чтение репозитория происходит медленнее и чем в '''Git''', и чем в Mercurial. При выводе истории изменений по одной и той же ветке '''Git''' не напрягается вообще, '''Mercurial''' напрягается немного, а '''Bazaar''' напрягается ощутимо. При том, что '''Git''' и '''Mercurial''' выводят не только историю изменений самой ветки, а также историю изменений, происходивших ''до создания ветки'' (помним, что ветки нечестные). Правда, я не исключаю, что под виндой ситуация с производительностью может быть совсем другая. А теперь снова о неприятном. Есть у Базаара одна небольшая, зато возникающая в достаточно простом случае, проблемка. То есть пусть бы она и появлялась, но очень редко — это можно терпеть. Но тут ситуация довольно частаяне так чтобы редкая.
Так вот. Всё начинается с банального — мы сделали изменение в '''Bazaar'''-клонированном SVN-репозитории, а кто-то тем временем сделал изменение '''в самом SVN-репозитории'''… Причём не важно, в каких файлах: даже если конфликтов в наших изменениях нет, проблема возникает всё равно (помним о том, что DVCS управляют «цельным» репозиторием). Что нам теперь остаётся делать? Ну конечно, мержиться. И merge успешно проходит. Но в случае '''Bazaar''' помните — после этого merge нужно сразу делать rebase и push в Subversion! Иначе, если до этого сделать ещё хотя бы один commit в Bazaar, push не удастсяпройдёт (он и не должен), а rebase не поможет или вывалится с исключением.
Хотите подробнее? Рассмотрим следующую последовательность действий:
<div style="height: 150px; overflow: scroll">{{:hg-rebase-better-than-bzr-ithelps.sh}}</div>
 
=== Итоги клонирования SVN MediaWiki ===
 
Место на диске:
* '''Git''' — 845 мб.
* '''Bazaar''' — 925 мб.
* '''Mercurial''' — 1633 мб.
 
«Нечестные» ветки (<tt>svn cp trunk/phase3 trunk/extensions branches/ветка/</tt>):
* '''Mercurial''' — корректно прицепились к trunk’у (!).
* '''Git''' — общая история у всех таких веток, но отдельная от trunk’а.
* '''Bazaar''' — история «ДО» создания нечестных веток потеряна.
 
Проблемы:
* '''Git''' — клонирование SVN идёт очень долго, много данных копируется повторно.
* '''Mercurial''' — течёт память, проблема с <tt>rev_map</tt> в середине клонирования.
* '''Bazaar''' — течёт память, проблемы с <tt>rebase</tt>.
== Управление патчами ==
Рассмотрим задачу управления набором патчей: есть некоторый проект, есть набор сторонних (например, ваших) патчей. Некоторые из них нужно накатывать в определённой последовательности, кроме того, и само ПО, и патчи не стоят на месте и могут меняться, и неплохо бы иметь также их историю. Можно, конечно, просто создать форк, но в этом случае ваша ветка, скорее всего, серьёзно разойдётся с оригинальной и «выделять» из неё отдельные фичи станет очень тяжело. Короче говоря, если кому-то хочется увидеть наглядный пример из разряда «нафига оно надо», выполните команду <tt>apt-get source mc</tt>, то есть, скачайте Debian-пакеты с исходными кодами для [http://www.midnight-commander.org/ Midnight Commander] — патчей там чуть меньше, чем 50. === quilt, MQ, bzr-loom, StGIT === Первое, что приходит на ум — это, конечно, аналоги [http://savannah.nongnu.org/projects/quilt quilt]'а, работающие поверх DVCS: [http://mercurial.selenic.com/wiki/MqExtension Mercurial Queues](MQ), [https://launchpad.net/bzr-loom Bazaar Loom], [http://www.procode.org/stgit/ StGIT]. Все они очень похожи и друг на друга, и на сам '''quilt'''. MQ и StGIT достаточно развиты и стабильны. bzr-loom же пока находится на стадии развития. '''quilt''' — вещь банальная, позволяющая автоматизировать тупое накатывание последовательности большого числа патчей и правку патча, который находится где-то в середине: можно откатить N верхних патчей, внести изменения в файлы и сказать <tt>refresh</tt>, и верхний на данный момент патч (то есть патч откуда-то из середины) обновится, дабы соответствовать внесённым изменениям. '''quilt''' создан на основе скриптов человека, который не использует системы контроля версий — Эндрю Мортона (Andrew Morton) — второго по значимости участника разработки ядра Linux после Линуса Торвальдса. Из реализаций '''quilt''' поверх DVCS первым появился именно '''MQ''' и долгое время, судя по всему, был «изюминкой» Mercurial’а, хотя на самом деле совсем не идеален — идея добавления и удаления истории из/в репозиторий всё-таки странновата, а патчи не хранятся в том же репозитории, что и код — то есть, при клонировании исчезают. Этого недостатка лишены и '''bzr-loom''', и '''StGIT'''.
'''quilt''' вещь банальная, позволяющая автоматизировать тупое накатывание последовательности большого числа патчей и правку патча, который находится где-то в середине: можно откатить N верхних патчей, внести изменения в файлы и сказать refresh, и верхний === Подход «по ветке на данный момент патч (то есть патч откуда-то из середины) обновится, дабы соответствовать внесённым изменениям. '''quilt''' создан на основе скриптов человека, который не использует системы контроля версий — Эндрю Мортона (Andrew Morton) — второго по значимости участника разработки ядра Linux после Линуса Торвальдса.патч» ===
Из реализаций Крут ли '''quilt поверх DVCS появился именно MQ и долгое время''', судя по всемунет ли — каждый решает сам для себя. Конечно, поддержке Debian-патчей на какой-нибудь Midnight Commander '''quilt''' очень… помогает. Тем не менее, был «изюминкой» Mercurial’ас моей точки зрения, хотя некорректно закладываться на жёстко последовательное применение всех патчей. На самом деле неидеален — идея добавления и удаления истории из/в репозиторий всё-таки странновата, а такие патчи не хранятся логично организовывать '''в том же репозиториивиде графа''' (графа зависимостей). Сразу будет видно, что и код — то естьбольшинство патчей независимы друг от друга, при клонировании исчезают. Этого недостатка лишены и bzr-loom, и StGITа реально существующие зависимости окажутся на виду.
Крут ли quiltТеперь вспомним, нет ли — каждый решает сам для себя. Конечночто мы рассматриваем DVCS и что они умеют очень хорошо управлять ветками, поддержке Debian-патчей на какой-нибудь Midnight Commander (их там а ревизии как раз организуются в районе 60-граф — и) quilt очень… помогает. Тем не менеепоймём, с моей точки зрениячто задачу управления патчами удобнее всего решать, некорректно закладываться заводя ''по отдельной ветке'' на жёстко последовательное применение всех патчейкаждый патч. На самом деле, такие патчи логично организовывать в виде графа Причём для этого есть даже расширения Mercurial '''[http://arrenbrecht.ch/mercurial/pbranch/ pbranch]''' (графа зависимостейот patch branches)и Git '''[http://repo. Сразу будет видно, что большинство патчей независимы друг or.cz/w/topgit.git TopGit]''' (от другаtopic branches). Для Bazaar’а подобного расширения, а зависимости окажутся на видуувы, нет.
Таким образом, задачу управления патчами удобнее всего решать, заводя по отдельной ветке на каждый патч. Причём даже есть расширения ==== Mercurial [http://arrenbrecht.ch/mercurial/pbranch/ pbranch] (от patch branches) и Git [http://repo.or.cz/w/topgit.git TopGit] (от topic branches). Для Bazaar’а подобного расширения, увы, нет.====
'''Mercurial''''овский '''pbranch''': хорошо. Умеет весьма немногое. Самые полезные команды — это <tt>'''pdiff'''</tt>, <tt>'''pgraph'''</tt> и <tt>'''pmerge'''</tt>. <tt>'''pdiff'''</tt> экспортирует текущий патч '''без его родителей''' в стандартном формате. <tt>'''pgraph'''</tt> показывает граф зависимостей патчей, из которого можно, по сути, понять, в какой последовательности их накатывать, если они сами уже экспортированы. Ну и просто вообще граф патчей — это удобно. <tt>'''pmerge'''</tt> объединяет изменения, произошедшие в зависимостях патча, в патч.
Другие команды расширения:
;reapply: применить некую уже закоммиченную ревизию в ветку патча.
Чего не хватает (а хочется):
* легко Легко создавать патчи, зависящие от нескольких других(хотя это можно делать и вручную).* легко Легко поддерживать ветку, содержащую объединение всех патчей — для развёртывания.* Удалять зависимости патчей.
Первые два пункта в pbranch делаются как-то уж совсем нелогично — нужно '''TopGitручками''': (исследую)прописать зависимость патча в файл <tt>.hg/pgraph</tt> и вызвать команду <tt>hg pmerge</tt>, которая автоматически объединит все пока что не объединённые зависимости в необходимые ветки. Очень странно, что предписано общаться через <tt>.hg/pgraph</tt> при том, что этот файл вообще-то не является никаким «окончательным хранилищем» — его скорее можно классифицировать, как кэш команды <tt>pgraph</tt> — если его удалить, он будет успешно воссоздан, и при клонировании репозитория он также не копируется.
ЗабавнаяЗато, кстатив отличие от TopGit, вещь'''pbranch''''евый репозиторий без проблем клонируется со всеми ветками и информацией о патчах, и документация на '''pbranch''' [http://arrenbrecht. Явно написана ch/mercurial/pbranch/index.htm весьма вменяема]… ===== Пример использования ===== Лично я, для управления патчами MediaWiki, входящими в состав CustIS’овской сборки MediaWiki, и хранящимися под SVN в виде набора diff-файлов, выбрал именно '''pbranch''' и следующую схему работы:* SVN-репозиторий компании содержит директорию <tt>custisinstall</tt> с конфигурационными файлами и патчами в виде diff’ов и директорию extensions с расширениями, написанными либо сильно модифицированными (по сути «форкнутыми») нами. Без веток, без меток.* Ветка <tt>default</tt> содержит импортируемый <tt>hgsubversion</tt>'ом SVN-репозиторий.* Ветка <tt>mediawiki</tt> содержит дистрибутив оригинальной MediaWiki в том виде, в каком он должен присутствовать в DocumentRoot’е, плюс расширения, слабо модифицированные (патчами) или вообще не модифицированные нами, в поддиректории <tt>extensions</tt>.* На основе ветки <tt>mediawiki</tt> создаются отдельные ветки для независимых друг от друга патчей в код MediaWiki и/или код расширений из ветки mediawiki.* Для патчей, зависящих от других, создаются ветки на основе веток этих патчей.* Ветка <tt>all</tt> содержит объединение всех веток патчей.* Ветка <tt>mergeinstall</tt> содержит объединение веток <tt>all</tt> и <tt>default</tt> и используется для развёртывания.* Все зависимости между ветками автоматически отслеживаются '''pbranch''''ем. Таким образом, для установки нашей сборки MediaWiki через Mercurial надо только клонировать репозиторий и обновиться до ветки mergeinstall — сразу же будут получены все патчи и расширения. При этом все патчи с помощью команды <tt>hg pdiff</tt> экспортируются в diff-файлы и коммитятся в Subversion, поэтому доступен и старый метод установки — Python-скрипт, выкачивающий из svn.wikimedia.org код MediaWiki, из локального Subversion’а — код нужных расширений и патчи, и накатывающий эти патчи на MediaWiki автоматически. ==== TopGit ==== '''TopGit''': тоже весьма хорошо, даже чуть получше (версия на момент тестирования была 0.8). А в будущем станет ещё лучше — по ходу просмотра справки по некоторым командам выводится по одному-два TODO — значит, они, наверное, появятся. Забавно, кстати, что '''TopGit''' явно написан в общем духе git-а (а — смесь скриптов на bash, perl и программ на C). «Головной» скрипт '''<tt>tg</tt>''' (TopGit) написан на шелле, и команды <tt>tg --help, tg -h, tg help</tt> и т. п. сначала вводят в недоумение — «<tt>no git repository here</tt>». Справку Нет, не подумайте, справку TopGit печатать умеет, но для этого сначала надо зайти в git-репозиторий :) типа ''Чего ты спрашиваешь? У тебя интерес реальный? Ты покупать будешь или нет?..'' '''TopGit''', как уже сказано, умеет побольше '''pbranch''', в частности, умеет 1-ую и 2-ую вышеупомянутые «хотелки» — команда <tt>tg create</tt> может создать новую ветку-патч на основе множества зависимостей, автоматически объединяя их и предлагая разрешать возникающие конфликты, а с помощью <tt>tg update</tt> можно обновлять изменения в зависимостях в ветки патчей, причём рекурсивно. На самом деле и то, и другое можно сделать и в '''pbranch''', и даже вообще без него, но придётся набрать чуть больше команд. Команды расширения: ;create: создать новую ветку-патч на основе одной или нескольких веток.;delete: удалить ветку-патч.;depend: редактировать зависимости.;export: экспортировать историю текущей ветки в виде quilt-серии или новой, «подчищенной», git-ветки.;import: импортировать коммиты в виде патчей.;info: аналог <tt>hg pstatus</tt>, выводит состояние ветки — сколько, чего и откуда надо обновить и т. п.;mail: отправка патчей по почте.;patch: аналоги <tt>hg diff</tt>, выводит текущий патч в виде diff + комментарий вверху.;push: отправляет изменения из tg-шной ветки.;remote: перевести внешние (remote-tracking) ветки под управление tg.;summary: выводит список патчей со статусами и/или граф зависимостей через [[lib:Graphviz|Graphviz]]. В ASCII-виде этот граф, к сожалению, не рисуется.;update: см.выше. Чего не хватает (а хочется): * Возможности клонирования репозитория с учётом TopGit’а.*: С клонированием Git, как известно, выпендривается своими «[http://www.gitready.com/beginner/2009/03/09/remote-tracking-branches.html Remote Tracking Branches]», а TopGit, к сожалению, не полностью основан на стандартных механизмах Git. Поэтому с помощью команд <tt>git clone</tt> или <tt>git pull</tt> скопировать репозиторий с сохранением всей информации TopGit невозможно. Между прочим, весьма серьёзный недостаток.* Удалять зависимости патчей.*: То есть по-настоящему удалять зависимости, а не просто отменять изменения. Но это в TODO перечислено и, вероятно, будет реализовано.
== Схема управления рабочими копиями ==
'''Mercurial''' говорит нам: на ровно 1 рабочую копию ровно 1 репозиторий, и иначе быть не может. Это и удобно — сказал <tt>hg up ветка_такая_то</tt>, пара файлов поменялась, и опа — ты уже в другой ветке. Это и неудобно — чтобы положить на диск одновременно две разных ветки, нужно обязательно клонировать репозиторий (поддержки checkout нет).
С '''Git''''ом ситуация почти такая же, как и с Mercurial’ом. 1 рабочая копия, 1 репозиторий. Хотя при клонировании данные репозитория можно и не копировать, задавая опцию <tt>--shared</tt>, но это скорее похоже на Bazaar’овские [http://doc.bazaar-vcs.org/latest/en/user-guide/stacked.html Stacked Branches], чем на Lightweight Checkout. Идея checkout’ов, или лёгких рабочих копий (или «идея .gitlink») [http://git.or.cz/gitwiki/SoC2007Ideas высказана для GSoC-2007], однако (пока ?) так и не реализована. Управление ветками в '''Bazaar''' вначале было гораздо хуже: на 1 ветку ровно 1 рабочая копия и ровно 1 репозиторий. Однако потом появилось уникальное: <tt>checkout</tt>'ы и [http://bazaar-vcs.org/SharedRepositoryTutorial Shared Repository], имеющий опцию <tt>--no-trees</tt>. Таким образом, стало возможно иметь сколько угодно репозиториев и сколько угодно рабочих копий. В Git и Mercurial этого нет. Переключать легковесную рабочую копию с ветки на ветку Bazaar тоже умеет — командой <tt>switch</tt>, для переключения ветки её надо превратить в легковесную рабочую копию командой <tt>bind</tt>. Тут надо сделать небольшое отступление: Bazaar имеет несколько идеологических моментов. Первый — это идея, гласящая, что '''''директории — не контейнеры веток, а сами ветки'''''. В одной директории, содержащей рабочую копию, не может содержаться нескольких веток. Существуют ещё [http://bazaar-vcs.org/SharedRepositoryTutorial разделяемые репозитории], но они сами по себе не содержат рабочей копии, а содержат директории, которые могут содержать рабочие копии. Идея, с моей точки зрения, далеко не лучшая. Например, из-за неё Bazaar не может, как Git и Mercurial, переключиться на произвольную ревизию и по коммиту автоматически ответвиться в сторону. В Bazaar можно только сделать <tt>revert</tt> («откат») к определённой версии. Рабочие файлы при этом изменятся, а «состояние» рабочей копии — нет. Считается, что рабочая копия ''всегда'' содержит последнюю сохранённую ревизию. Вторая идея — это '''''идея mainline''''', то есть, идея поддержки «центральной» ветки разработки на уровне системы контроля версий. С хвалебной точки зрения про mainline можно почитать в блоге «Базарный день» (части [http://bzr-day.blogspot.com/2009/09/mainline-1.html 1], [http://bzr-day.blogspot.com/2009/09/mainline-2.html 2], и будут ещё). Я же выступлю с критической точки зрения — никакая это не гениальная практика, а просто ещё один хардкод, который можно выразить простыми словами: после синхронизации рабочих копий ''HEAD-ревизия'' (ревизия, не имеющая дочерних — в терминах Mercurial), ''всегда ровно одна''. Все другие ''HEAD’ы'' физически находятся в других директориях (= ветках), ещё не синхронизированных с данной. То есть, Bazaar заставляет пользователя объединять историю при каждой синхронизации с другой веткой. Из ''идеи mainline'' сразу следует определённое неудобство: при синхронизации '''меняется история''' веток (даже твоей, любимой, неприкосновенной) — ревизии, внесённые ранее локально, могут быть перемещены в «под-узлы» ревизии-объединения, которую в свою ветку внесла удалённая сторона. История меняется так, чтобы в конечном счёте история всех веток выглядела одинаково. То есть, «история истории» теряется, а ещё из перестановок ревизий в истории сразу следуют проблемы работы с Subversion.
Управление ветками в '''Bazaar''' вначале было хуже всехКороче говоря, да, а потом стало лучше всех (по возможностям)это просто очередной «хардкод». Вначале он говорил нам: То ли — рассчитанный на 1 ветку ровно 1 рабочая копия и ровно 1 репозиторий. А когда исправилсято, что если дать людям свободу, стало можно создать они не будут в состоянии достаточно часто объединяться с основной веткой, то ли — просто унаследованный от Arch’а ([http[wikipedia://bazaar-vcs.org/SharedRepositoryTutorial Shared RepositoryGNU Arch|GNU Arch] с опцией <tt>--no-trees</tt>, а потом сколько захочется рабочих копий <tt>checkout</tt>'ами. Переключить рабочую копию с ветки на ветку также можно — командой <tt>switch</tt> (для этого также нужно превратить ветку в checkout командой <tt>bind</tt>] — прародитель Bazaar’а).
Тем не менееИ если уж зашла речь о недостатках '''Bazaar'''’а, лично я против базаараещё следует отметить, что он не по причине какихумеет показывать консольные ASCII-либо псевдографические графы ревизий. ''недоработок'Git', а по причине ''идеи mainlineи ''; того, что директории — это не контейнеры веток, а сами ветки; показа отдельно «своих» и «чужих» ревизий в каждой ветке; и 'Mercurial''изменения истории'умеют — и это очень удобно. А разработчики Bazaar считают их отсутствие фичей — ревизии, типа, сортируются, зачем графы? '' (плясок ревизий) при объединениях. ИМХО — лучше показывать граф ревизий и ничего никуда не переставлятьправда, только добавлять рёбра. Особенно учитываязачем? стройте графы сами, что базаар в нутрях всё равно работает через графы (а голове! как ещёне умеете?!!).''
[[Категория:Разработка]]
[[Категория:Статьи]]

Навигация