- Сходство и различие между Mercurial и Git
- Немного истории
- Cходство
- Отличия
- Практические аспекты использования
- Выводы
- Национальная библиотека им. Н. Э. Баумана Bauman National Library
- Персональные инструменты
- Mercurial
- Содержание
- Описание
- Концепции
- Рабочий процесс
- Консольная программа
- Логическая структура наборов изменений
- Идентификация наборов изменений
- Номер ревизии
- Идентификатор набора изменений
- Метки
- Название ветки
- Неочевидные моменты
- Дополнительные средства
- Проекты, использующие Mercurial
Сходство и различие между Mercurial и Git
Немного истории
Толчком к созданию обеих систем, как Mercurial, так Git, послужило одно событие 2005 года. Всё дело было в том, что в упомянутом 2005 году ядро системы Linux потеряло возможность бесплатного использования системы контроля версий BitKeeper. После пользования BitKeeper в течение трёх лет разработчики ядра привыкли к его распределённому рабочему процессу. Автоматизированная работа с патчами сильно упрощала процесс учёта и слияния изменений, а наличие истории за продолжительный период времени позволяло проводить регрессию.
Другой немаловажной частью процесса разработки ядра Linux стала иерархическая организация разработчиков. В вершине иерархии стоял Диктатор и много Лейтенантов, отвечавших за отдельные подсистемы ядра. Каждый Лейтенант принимал или отклонял отдельные изменения в пределах своей подсистемы. Линус, в свою очередь, затягивал их изменения и публиковал их в официальном хранилище ядра Linux. Любой инструмент, вышедший на замену BitKeeper, должен был реализовывать такой процесс.
Третьим критичным требованием к будущей системе была скорость работы с большим количеством изменений и файлов. Ядро Linux — это очень большой проект, принимающий тысячи отдельных изменений от тысяч различных людей.
Среди множества инструментов подходящего не нашлось. Практически одновременно Мэт Макол (Matt Mackall) и Линус Торвальдс (Linus Torvalds) выпускают свои системы контроля версий: Mercurial и Git соответственно. В основу обеих систем легли идеи появившегося двумя годами ранее проекта Monotone.
Cходство
Отличия
Несмотря на общность идей и высокоуровневого функционала, реализации систем на низком уровне в значительной степени отличны.
Хранение истории
И Git, и Mercurial идентифицируют версии файлов по их контрольной сумме. Контрольные суммы отдельных файлов объединяются в манифесты. В Git манифесты называются деревьями, в которых одни деревья могут указывать на другие. Манифесты непосредственно связаны с ревизиями/фиксациями.
Mercurial для улучшения производительности пользуется специальным механизмом хранения Revlog. Каждому файлу, помещенному в хранилище, сопоставляется два других: индекс и файл с данными. Файлы с данными содержат слепки и дельта-слепки, которые создаются только когда количество отдельных изменений файла превышает некоторое пороговое значение. Индекс служит инструментом эффективного доступа к файлу с данными. Дельты, полученные в результате изменения файлов под контролем версий, добавляются только в файлы с данными. Для того, чтобы правки из разных мест файла объединить в одну ревизию, используется индекс. Ревизии отдельных файлов складываются манифесты, а из манифестов — фиксации. Этот метод зарекомендовал себя весьма эффективным в деле создания, поиска и вычисления различий в файлах. Также к достоинствам метода можно отнести компактность по отношению к месту на диске и достаточно эффективный протокол передачи изменений по сети.
В основе модели хранения Git лежат большие объектные бинарные файлы (BLOB). Каждая новая ревизия файла — это полная копия файла, чем достигается быстрое сохранение ревизий. Копии файлов сжимаются, но, всё равно, имеют место большие объёмы дублирования. Разработчики Git применили методы упаковки данных для снижения требований к объёму хранилища. По существу они создали нечто похожее на Revlog для указанного момента времени. Полученные в результате упаковки пакеты отличаются от Revlog’а, но преследуют ту же цель — сохранить данные, эффективно расходуя дисковое пространство. В виду того, что Git сохраняет слепки файлов, а не инкремент, фиксации могут легко создаваться и уничтожаться. Если при анализе требуется посмотреть разницу между двумя различными фиксациями, то в Git разность (diff) вычисляется динамически.
Ветвление
Ветвление — очень важная часть систем управления конфигураций, т.к. оно позволяет проводить параллельную разработку новой функциональности, сохраняя стабильность старой. Поддержка ветвления присутствует как в Git, так и в Mercurial. Отличия формата хранения истории нашли своё отражение и в реализации ветвления. Для Mercurial ветка — это некая отметка, которая прикрепляется к фиксации навсегда. Эта отметка глобальна и уникальна. Любой человек, затягивающий изменения из удалённого хранилища, увидит все ветки в своём хранилище и все фиксации в каждой из них. Для Mercurial ветки — это публичное место разработки вне основного ствола. Имена веток публикуются среди всех участников, поэтому в качестве имен обычно используют устойчивые во времени номера версий.
Ветки Git, по сути, являются лишь указателями на фиксации. В разных клонах хранилища ветки с одинаковыми названиями могут указывать на разные фиксации. Ветки в Git могут удаляться и передаваться по отдельности (каждая уникально идентифицируется по локальному имени в хранилище-источнике).
Практические аспекты использования
Различия в реализациях Git и Mercurial можно проиллюстрировать на примерах.
Mercurial позволяет легко фиксировать изменения, проталкивать и вытягивать их с поддержкой всей предыдущей истории. Git не заботится о поддержке всей предыдущей истории, он только фиксирует изменения и создаёт указатели на них. Для Git не имеет значения предыдущая история и на что раньше ссылались указатели, важно то, что актуально в текущий момент. Существует даже инструмент, гарантирующий сохранность локальной истории при вытягивании изменений из внешнего хранилища — fast-forward merge. Если этот механизм включен, то Git будет сообщать об изменениях, которые не могут быть улажены без продвижения по истории вперёд. Данные ошибки можно не принимать во внимание, если поступившие изменения ожидались.
При выполнении отката фиксации или затягивания со слиянием Git просто меняет указатель ветки на предыдущую фиксацию. В действительности в любой момент времени, когда требуется откатиться в некоторое предыдущее состояние, Git ищет в логе соответствующую контрольную сумму и сообщает какая фиксация ей соответствует. Как только что-то зафиксируется в Git, то всегда можно к этому состоянию вернуться. Для Mercurial существуют случаи, когда невозможно полностью вернуться в исходное состояние. Т.к. Mercurial для решения какой-либо проблемы создает фиксацию, то в некоторых случаях затруднительно переместиться назад с учётом свежего изменения.
Для решения различных проблем в Mercurial существуют расширения. Каждое расширение решает свои проблемы хорошо, если существует само по себе. Существует даже некоторые расширения, обеспечивающие сходную функциональность, но разными способами.
Для примера рассмотрим работу с отложенной историей. Допустим, нам необходимо записать изменения из рабочей копии без фиксации в хранилище. Git предлагает использовать stash. Stash — это фиксация или ветка, которые не сохраняются в обычном месте. Stash не показывается, когда выводится список веток, но всеми инструментами он трактуется как ветка. Если аналогичная функциональность требуется Mercurial, то можно использовать расширения attic или shelve. Оба этих расширения хранят «отложенную» историю в качестве файлов в хранилище, которые могут быть при необходимости зафиксированы. Каждое расширение решает проблему немного по-своему, поэтому имеет место несогласованность форматов.
Другой пример, команда git commit —amend. Если нужно изменить самую последнюю фиксацию, например, добавить что-нибудь забытое или изменить комментарий, то команда git commit —amend создаст полностью новый набор файловых объектов, деревьев и объектов фиксации. После этого обновляется указатель ветки. Если далее потребуется откатить изменения, то необходимо только вернуть указатель на предыдущую фиксацию командой git reset —hard HEAD@<1>. Чтобы повторить это в Mercurial потребуется откатить фиксацию, затем создать новую, далее импортируем содержимое последней фиксации при помощи расширения queue, дополняем её и делаем новую фиксацию.
Следует заметить, что ни одно из перечисленных выше дополнений не использует возможности формата хранения Mercurial, и таким образом они существуют исключительно как самостоятельная надстройка над ним.
Выводы
В последнем разделе этой статьи хотел бы высказать собственное мнение по выбору системы контроля версий. И Mercurial, и Git хороши в своих сегментах.
Например, для целей ведения коммерческого программного проекта мне больше импонирует Mercurial.
- Строгая работа с историей в Mercurial гарантирует возможность учёта и поиска первоначального источника ошибки.
- После слияния с веткой в Git мы рискуем получить гига-патч, в котором где-то будет скрываться ошибка.
- Глобальные ветки также дают возможность контроля за работой коллег при регулярной синхронизации с центральным хранилищем.
Для хранения бинарных файлов, например, электронной библиотеки, Git подходит лучше. По сравнению с Mercurial он не ориентирован на расчет дельты файлов, что для бинарного содержимого не очень эффективно. Сами файлы меняются редко, а основные операции с ними — это перемещение и добавление. По моим собственным наблюдениям папка хранилища Git с историей моей библиотеки сопоставима по размерам с рабочей копией с окрестностью примерно 10%.
Источник
Национальная библиотека им. Н. Э. Баумана
Bauman National Library
Персональные инструменты
Mercurial
Разработчики: | Matt Mackall |
---|---|
Выпущена: | 19 April 2005 года ; 16 years ago ( 2005-04-19 ) |
Постоянный выпуск: | 4.1 / 1 February 2017 года ; 4 years ago ( 2017-02-01 ) |
Написана на: | Python, C |
Операционная система: | UNIX, Windows, Mac OS X |
Тип ПО: | Git client |
Лицензия: | GNU GPL v2+ |
Веб-сайт | mercurial-scm .org |
Mercurial (ртутный, подвижный), он же Hg (от обозначения химического элемента ртути) — кроссплатформенная распределённая система управления версиями, разработанная для эффективной работы с очень большими репозиториями кода. В первую очередь она является консольной программой.
Содержание
Описание
Система Mercurial написана на Python, хотя чувствительные к производительности части (например, своя реализация diff ) выполнены в качестве модулей-расширений на C. Mercurial первоначально была написана для Linux, позже портирована под Windows, Mac OS X и большинство Unix-систем. Репозитории Mercurial управляются при помощи утилиты командной строки hg , но есть и GUI–интерфейсы.
Наряду с традиционными возможностями систем контроля версий, Mercurial поддерживает полностью децентрализованную работу (отсутствует понятие основного хранилища кода), ветвление (возможно вести несколько веток одного проекта и копировать изменения между ветками), слияние репозиториев (чем и достигается «распределённость» работы). Поддерживается обмен данными между репозиториями через HTTP/HTTPS, SSH и вручную при помощи упакованных наборов изменений.
Утилита hg обладает компактным интерфейсом, и Mercurial считается более простой в освоении системой, чем, например, git.
Концепции
Рабочий процесс
Mercurial является распределённой (децентрализованной) системой контроля версий. Это означает, что рабочий процесс, как правило, выглядит следующим образом:
- На личном компьютере создаётся новый репозиторий (путём клонирования существующего репозитория, создания нового и т. п.);
- В рабочей директории данного репозитория изменяются/добавляются/удаляются файлы;
- Выполняется фиксация ( commit ) изменений в данный репозиторий (то есть в локальный репозиторий на личном компьютере);
- Шаги 2 и 3 повторяются столько раз, сколько необходимо;
- При необходимости производится синхронизация изменений с другими репозиториями: забираются ( pull ) чужие наборы изменений и/или отдаются ( push ) собственные.
То есть вся повседневная работа происходит в локальном репозитории, а когда возникает необходимость, производится отправка результатов своей работы в один или несколько других репозиториев. Количество шагов при работе с отдаленными репозиториями можно сократить, если настроить Mercurial на автоматическую отправку изменений в другие репозитории при выполнении фиксации.
Консольная программа
Консольная программа реализована таким образом, что название любой команды можно сокращать до тех пор, пока её имя остаётся однозначным. Плюс некоторые команды имеют псевдонимы. Например, вместо hg commit можно написать hg commi , hg comm или hg com , но если написать hg c , то Mercurial откажется выполнять эту команду, сообщив, что «команда 'c' неоднозначна» и приведя список команд, которые попадают под это сокращение. Использовать hg co в качестве сокращения для hg commit нельзя, так как это псевдоним для команды hg update, однако доступно сокращение hg ci .
Логическая структура наборов изменений
При вызове команды hg commit выполняется фиксация изменений. При этом программа сохраняет в репозиторий набор изменений(changeset или ревизия). Физически происходят те же изменения, что и у вас, но сохраняются они в служебные файлы, а не в копии.
Как правило, все наборы изменений, которые были зафиксированны, отображают в виде большой связной сети(графа), где каждый набор изменений связан с одним или двумя другими.
Узнать идентификаторы родительских наборов изменений, с которыми связаны зафиксированные наборы изменений можно с помощью команды hg log —debug . У каждого набора изменений будет два родителя (благодаря чему возможно ветвление внутри репозитория, см. hg -v help branch ). Значение «-1:0000000000000000000000000000000000000000» означает отсутствие родителя. Например, у самого первого набора изменений в репозитории данное значение будет проставлено для обоих родителей, а у последующих данное значение будет проставлено для второго родителя (если для них в репозитории не использовалось ветвление), а для первого родителя будет проставлен идентификатор от предыдущего набора изменений.
Рабочую директорию также полезно представлять в виде такого же набора изменений (который пока не зафиксирован, но, возможно, вскоре также будет зафиксирован). Рабочая директория также связана с одним или двумя родительскими наборами изменений, узнать о которых можно с помощью команды hg parents . После фиксации изменений данные родители станут родителями для нового (уже зафиксированного) набора изменений.
Идентификация наборов изменений
Ревизии распознают по следующим признакам:
- Номеру ревизии;
- Идентификатору набора изменений;
- Меткам (Тег);
- Имени ветки.
Номер ревизии
Номер ревизии представляет собой целое число, отражающее порядок, в котором наборы изменений были добавлены в хранилище. Номер ревизии начинается с нуля, присваивается набору изменений автоматически и может использоваться для идентификации наборов изменений. Номер ревизии для одного и того же набора изменений может различаться в каждом из клонов хранилища. В выводе команды hg log номер ревизии можно увидеть перед двоеточием (например, «4:e1be1898f374»).
Идентификатор набора изменений
Идентификатор набора изменений представляет собой SHA-1 хеш, состоящий из цифр и букв «a, b, c, d, e, f», например, «e1be1898f3747386c41c8a5c5776e87373f6d3d3». Идентификатор набора изменений присваивается каждому набору изменений автоматически, вычисляется на основе содержимого этого набора изменений, поэтому соответствует одному и тому же набору изменений во всех репозиториях. Вероятность коллизии, когда для двух разных наборов изменений будет сгенерирован один и тот же SHA-1 хеш, крайне мала.
Mercurial не требует ввода полной строки идентификатора при использовании его в командах, ему достаточно лишь той его начальной части, которая однозначно идентифицирует требуемый набор изменений (в противном случае, Mercurial сообщит о неоднозначности). В выводе команды hg log идентификатор набора изменений можно увидеть после двоеточия (например, «4:e1be1898f374»). Без параметра —debug команда hg log выводит не полный, а сокращенный (из 12 символов) идентификатор набора изменений.
Метки
В дополнение к номеру ревизии и идентификатору набора изменений, Mercurial предоставляет возможность присваивать каждому набору изменений одно или более произвольных символических имен, называемых метками (или тегами). Присваиваются метки с помощью команды hg tag , а посмотреть все добавленные метки можно с помощью команды hg tags . Имя метки не может содержать некоторые символы (например «: «), о чём, в случае необходимости, Mercurial сообщит при выполнении команды hg tag .
Везде, где в командах можно указать идентификатор набора изменений, можно подставить имя метки.
Название ветки
Каждая ветка имеет собственное название. Оно указывается при создании ветки и больше никогда не изменяется.
Неочевидные моменты
- Если в качестве идентификатора ревизии какой-либо команде передано число, то Mercurial будет считать, что ему передан номер ревизии и будет выполнять проверку на неоднозначность с сокращенным идентификатором наборов изменений только в том случае, если отсутствует набор изменений с указанным номером ревизии. Например, если в репозитории существует один набор изменений с номером ревизии «6» и другой набор изменений с идентификатором «647362ac74d76124267215af1a3f94aa9707dfdf» (начинается с цифры «6»), то команда hg log -r 6 выдаст информацию о первом наборе изменений, не сообщив о неоднозначности. Поэтому, если глобальный идентификатор начинается с цифры, полезно всегда сокращать его лишь до тех пор, пока в нём не встретится буква. Данное поведение наблюдалось в версии 2.2.1 под Mac OS X 10.7.4.
- Если создать метку с именем, например, «5», в то время как в репозитории существует (или появится в будущем) набор изменений с номеров ревизии «5», то Mercurial будет искать в первую очередь наборы изменений по номеру ревизии. Но если создать метку с именем, например, «e1be», в то время как в репозитории существует (или появится в будущем) набор изменений с идентификатором наборов изменений, начинающимся с «e1be», то Mercurial будет искать наборы изменений в первую очередь уже по меткам. Притом, в обоих случаях о неоднозначности сообщено не будет. По этой причине не рекомендуется создавать метки, состоящие только из цифр и/или букв «a, b, c, d, e, f». Данное поведение наблюдалось в версии 2.2.1 под Mac OS X 10.7.4.
- Нельзя добавить в репозиторий пустую папку (для решения этой проблемы можно положить в папку любой файл, например, readme.txt). Такое поведение связано с тем, что Mercurial не отслеживает папки, а только файлы. Поведение реализовано осознанно для упрощения системы и пока что изменений не планируется.
Дополнительные средства
В комплекте с Mercurial поставляются CGI-сценарии для предоставления веб-интерфейса к репозиториям.
Есть графическая оболочка TortoiseHg, работающая как под Windows (с интеграцией в Explorer), так и под Linux (в виде отдельного приложения или с интеграцией в Nautilus). Существует разрабатываемый консольный клиент hgtui для Linux и Windows (с использованием cygwin).
Ряд сред разработки имеет возможности для работы с Mercurial, например Microsoft Visual Studio, IntelliJ IDEA, Eclipse, Qt Creator (начиная с версии 2.0), PIDA, NetBeans. Возможна работа с Mercurial из Emacs c помощью входящего в Emacs универсального пакета VC.
Экспериментальная поддержка Mercurial есть в системе Trac. Проект Redmine также поддерживает репозитории Mercurial.
При помощи утилиты Tailor или расширения convert репозиториев других систем контроля версий, включая CVS, Subversion, Git, Perforce, Darcs, GNU Arch, Bazaar.
Проекты, использующие Mercurial
Значительное количество проектов по разработке свободного программного обеспечения использует Mercurial в качестве основной системы контроля версий. В их числе:
Поддерживаются Mercurial-зеркала основных репозиториев других проектов, например: GCC, GNU Emacs и Linux.
Источник