Ответ 1
Отказ от ответственности: Я использую Git, следую за Git разработкой в списке рассылки Git и даже вношу свой вклад в Git (главным образом gitweb). Я знаю Mercurial из документации, а некоторые - из обсуждения IRC-канала #revctrl на FreeNode.
Спасибо всем людям за #mercurial IRC-канал, которые предоставили помощь Mercurial для этой записи
Резюме
Здесь было бы неплохо иметь некоторый синтаксис для таблицы, что-то вроде расширения PHPMarkdown/MultiMarkdown/Maruku Markdown
- Структура хранилища: Mercurial не допускает слияния осьминогов (с более чем двумя родителями) и не тегирует объекты без фиксации.
- Теги: Mercurial использует файл версии
.hgtags
со специальными правилами для тегов репозитория, а также поддерживает локальные теги в.hg/localtags
; в тегах Git ссылки refs находятся в пространстве именrefs/tags/
и по умолчанию автоматически выбираются при извлечении и требуют явного нажатия. - Филиалы: В стандартном рабочем процессе Mercurial используется анонимные заголовки; Git использует ветки с легким именем и имеет специальные ветки (ветки удаленного отслеживания), которые следуют за ветками в удаленном репозитории.
- Именование и диапазоны версий: Mercurial предоставляет номера версий, локальные репозитории и основывает относительные изменения (считая от tip, т.е. текущую ветвь) и диапазоны пересмотра этой локальной нумерации; Git предоставляет способ ссылаться на ревизию относительно кончика ответвления, а диапазоны ревизий являются топологическими (на основе графика изменений).
- Mercurial использует переименование отслеживания, а Git использует определение переименования для работы с переименованием файлов
- Сеть: Mercurial поддерживает SSH и HTTP "интеллектуальные" протоколы и статический протокол HTTP; современный Git поддерживает SSH, HTTP и Git "умные" протоколы и протокол HTTP (S) "немой". Оба имеют поддержку файлов пакетов для автономного транспорта.
- Mercurial использует расширения (плагины) и установлен API; Git имеет скриптабельность и установленные форматы.
Есть несколько вещей, которые отличаются от Mercurial от Git, но есть и другие вещи, которые делают их похожими. Оба проекта заимствуют идеи друг от друга. Например, команда hg bisect
в Mercurial (ранее расширение bisect) была вдохновлена командой git bisect
в Git, а идея git bundle
был вдохновлен hg bundle
.
Структура хранилища, сохранение версий
В Git в объектной базе данных есть четыре типа объектов: объекты blob, которые содержат содержимое файла, иерархические древовидные объекты, которые хранят структуру каталогов, включая имена файлов и соответствующие части разрешений на файлы (исполняемые разрешения для файлов, являющийся символической ссылкой), объект фиксации, который содержит информацию об авторстве, указатель на моментальный снимок состояния репозитория при ревизии, представленный фиксацией (через древовидный объект верхнего каталога проекта) и ссылки на ноль или более родителей, и тег-объекты, которые ссылаются на другие объекты и могут быть подписаны с использованием PGP/GPG.
Git использует два способа хранения объектов: свободный формат, где каждый объект хранится в отдельном файле (эти файлы записываются один раз и никогда не изменяются) и в упакованном формате, где многие объекты хранятся дельта-сжатыми в отдельный файл. Атоматичность операций обеспечивается тем фактом, что ссылка на новый объект записывается (атомарно, используя трюк create + rename) после написания объекта.
Хранилища Git требуют периодического обслуживания с помощью git gc
(для уменьшения дискового пространства и повышения производительности), хотя в настоящее время Git делает это автоматически. (Этот метод обеспечивает лучшее сжатие репозиториев.)
Mercurial (насколько я понимаю) хранит историю файла в файловом журнале (вместе, я думаю, с дополнительными метаданными, такими как отслеживание переименований и некоторая вспомогательная информация); он использует плоскую структуру, называемую манифест, для хранения структуры каталогов и структуру под названием changelog, которая хранит информацию о наборах изменений (ревизий), включая сообщение о фиксации и ноль, один или два родителя.
Mercurial использует журнал транзакций для обеспечения атомарности операций и полагается на усечение файлов для очистки после неудачной или прерванной операции. Ревлоги только для добавления.
Рассматривая структуру репозитория в Git по сравнению с Mercurial, можно видеть, что Git больше похож на объектную базу данных (или файловую систему, ориентированную на контент), а Mercurial больше похожа на традиционную реляционную базу данных с фиксированным полем.
Различия:
В Git объекты дерева образуют иерархическую структуру ; в файле манифеста Mercurial находится плоская структура. В Git хранилище объектов blob одна версия содержимого файла; в Mercurial filelog хранится целая история одного файла (если мы не учитываем здесь какие-либо осложнения с переименованиями). Это означает, что существуют различные области операций, в которых Git будет быстрее Mercurial, все остальные считаются равными (например, слияния или показ истории проекта), а также области, где Mercurial будет быстрее, чем Git (например, применение патчи или показ истории одного файла). Эта проблема может быть не важна для конечного пользователя.
Из-за фиксированной записи структуры Mercurial changelog, в Mercurial может быть только до двух родителей; Commit в Git может иметь более двух родителей (так называемое "слияние осьминогов" ). Хотя вы можете (теоретически) заменить octopus merge на серию двух родительских слияний, это может вызвать осложнения при конвертации между репозиториями Mercurial и Git.
Насколько я знаю, Mercurial не имеет эквивалента аннотированных тегов (объектов тега) из Git. Особым случаем аннотированных тегов являются подписанные теги (с подписью PGP/GPG); эквивалент в Mercurial может быть выполнен с использованием GpgExtension, расширение которого распространяется вместе с Mercurial. Вы не можете отмечать неблокирующий объект в Mercurial, как вы можете в Git, но это не очень важно, я думаю (некоторые репозитории Git используют tagged blob для распространения открытого ключа PGP для использовать для проверки подписанных тегов).
Ссылки: ветки и теги
В Git ссылки (ветки, ветки удаленных следов и теги) находятся вне DAG коммитов (как и должно быть). Ссылки в пространстве имен refs/heads/
(локальные ветки) указывают на фиксацию и обычно обновляются "git commit"; они указывают на наконечник (головку) ветки, поэтому такое имя. Ссылки в пространстве имен refs/remotes/<remotename>/
( ветки удаленного отслеживания) указывают на фиксацию, отслеживание ветвей в удаленном репозитории <remotename>
и обновляются с помощью "git fetch" или эквивалентного. Ссылки в пространстве имен refs/tags/
( теги) обычно указывают на фиксации (легкие теги) или тег-объекты (аннотированные и подписанные теги) и не предназначены для изменения.
Метки
В Mercurial вы можете дать постоянное имя ревизии с помощью тега ; теги хранятся аналогично шаблонам игнорирования. Это означает, что глобально видимые теги хранятся в контролируемом версией файле .hgtags
в вашем репозитории. Это имеет два последствия: во-первых, Mercurial должен использовать специальные правила для этого файла для получения текущего списка всех тегов и для обновления такого файла (например, он читает последнюю исправленную версию файла, а не в настоящее время проверенную версию); во-вторых, вы должны зафиксировать изменения этого файла, чтобы новый тег был видимым для других пользователей/других репозиториев (насколько я понимаю).
Mercurial также поддерживает локальные теги, хранящиеся в hg/localtags
, которые не видны другим (и, конечно, не подлежат передаче)
В тегах Git фиксируются (константы) именованные ссылки на другие объекты (обычно тег-объекты, которые в свою очередь указывают на фиксации), хранящиеся в пространстве имен refs/tags/
. По умолчанию при извлечении или нажатии набора изменений, Git автоматически извлекает или толкает теги, которые указывают на выборку или перетаскивание ревизий. Тем не менее вы можете в какой-то степени контролировать, какие теги извлекаются или нажимаются.
Git обрабатывает легкие теги (указывающие непосредственно на фиксации) и аннотированные теги (указывающие на тег-объекты, которые содержат сообщение тега, которое необязательно включает подпись PGP, которое, в свою очередь, указывает на фиксацию) несколько иначе, например, по умолчанию оно считает только аннотированные теги при описании коммитов с использованием "git описывают".
Git не имеет строгого эквивалента локальных тегов в Mercurial. Тем не менее, рекомендации Git рекомендуют настроить отдельный публичный открытый репозиторий, в который вы нажимаете готовые изменения и из которых клонируются и извлекаются другие. Это означает, что теги (и ветки), которые вы не нажимаете, являются приватными для вашего репозитория. С другой стороны, вы также можете использовать пространство имен, отличное от heads
, remotes
или tags
, например local-tags
для локальных тегов.
Личное мнение:. По моему мнению, теги должны находиться вне графика ревизии, поскольку они являются внешними по отношению к нему (они являются указателями на график изменений). Теги должны быть не версиями, а переносимыми. Меркурийный выбор использования механизма, аналогичного механизму игнорирования файлов, означает, что он либо должен обрабатывать .hgtags
специально (файл в дереве является переносимым, но обычным версией), либо имеют теги, которые являются локальными (.hg/localtags
не является версией, но непереводимым).
Филиалы
В Git локальная ветвь (ветвь или ветвь ветки) является именованной ссылкой на фиксацию, где можно вырастить новые коммиты. Филиал также может означать активную линию развития, т.е. Все фиксации достижимы от кончика ответвления. Локальные ветки находятся в пространстве имен refs/heads/
, так, например, полное имя ветки "master" - "refs/heads/master" .
Текущая ветвь в Git (означает выделенную ветку и ветку, где будет выполняться новая фиксация) - это ветвь, на которую ссылается ссылка HEAD. Можно указывать HEAD непосредственно на фиксацию, а не на символическую ссылку; эта ситуация нахождения на анонимной неназванной ветки называется отсоединенной HEAD ( "git branch" показывает, что вы находитесь на "(без ветки)" ).
В Mercurial есть анонимные ветки (ветки ветки), и можно использовать закладки (через расширение закладки). Такие ветки вкладок являются чисто локальными, и эти имена были (до версии 1.6) не переносимы с использованием Mercurial. Вы можете использовать rsync или scp для копирования файла .hg/bookmarks
в удаленный репозиторий. Вы также можете использовать hg id -r <bookmark> <url>
, чтобы получить идентификатор ревизии текущего наконечника закладки.
Так как 1.6 закладки могут быть нажаты/выведены. На странице BookmarksExtension есть раздел Работа с удаленными репозиториями. Существует разница в том, что в названиях Mercurial-закладки глобальны, тогда как определение 'remote' в Git описывает также сопоставление имен веток из имен в удаленном репозитории с именами локальных ветвей удаленного отслеживания; например, отображение refs/heads/*:refs/remotes/origin/*
означает, что в удаленном репозитории можно найти состояние "ведущей" ветки ( "refs/heads/master" ) в ветке удаленного отслеживания "источник/мастер" ( "refs/remotes/origin/master" ").
Mercurial имеет также так называемые именованные ветки, где имя ветки внедрено в фиксации (в наборе изменений). Такое имя глобально (передается при извлечении). Эти имена веток постоянно записываются как часть метаданных changeet\u2019s. С помощью современного Mercurial вы можете закрыть "named branch" и прекратить запись названия ветки. В этом случае концы ветвей вычисляются на лету.
Mercurial "названные ветки" должны, на мой взгляд, называться присваивать метки, потому что это то, что они есть. Бывают ситуации, когда "названная ветвь" может иметь несколько советов (множественные бездетные коммиты) и может также состоять из нескольких непересекающихся частей графика изменений.
В Git нет эквивалента этих "встроенных ветвей" Mercurial; Более того, философия Git заключается в том, что, хотя можно сказать, что ветвь включает в себя некоторую фиксацию, это не означает, что фиксация принадлежит какой-либо ветке.
Обратите внимание, что документация Mercurial по-прежнему предлагает использовать отдельные клоны (отдельные репозитории), по крайней мере, для долгоживущих ветвей (отдельная ветвь для рабочего процесса репозитория), а также ветвление путем клонирования.
Филиалы в нажатии
Mercurial по умолчанию нажимает все головки. Если вы хотите нажимать одну ветвь (одиночная голова), вам нужно указать версию ревизии ветки, которую вы хотите нажать. Вы можете указать ответную подсказку по ее номеру ревизии (локально в репозиторий), по идентификатору ревизии, по имени закладки (локально в репозиторий, не передается) или по имени встроенной ветки (с именем branch).
Насколько я понимаю, если вы нажмете целый ряд ревизий, которые содержат коммиты, помеченные как "на определенной ветки" в языке Mercurial, у вас будет эта "именованная ветвь" в репозитории, на который вы нажимаете. Это означает, что имена таких встроенных ветвей ( "названные ветки" ) являются глобальными (относительно клонов данного репозитория/проекта).
По умолчанию (с учетом push.default
параметра конфигурации) "git push" или "git push < remote > " Git будет нажимать соответствующие ветки, т.е. только те локальные ветки, у которых их эквивалент уже присутствует в удаленном репозитории, в который вы входите. Вы можете использовать опцию --all
для git -push ( "git push -all" ), чтобы нажать все ветки, вы можете использовать "git push < remote > < branch > " для нажатия заданной отдельной ветки, и вы можете использовать "git push < remote > HEAD", чтобы нажать текущую ветвь.
Все вышесказанное предполагает, что Git не настроен, какие ветки нажимают через переменные конфигурации remote.<remotename>.push
.
Филиалы в выборке
Примечание: здесь я использую терминологию Git, где "выборка" означает загрузку изменений из удаленного репозитория без интеграции этих изменений с локальной работой. Это то, что делает "git fetch
" и "hg pull
".
Если я правильно понял, по умолчанию Mercurial извлекает все главы из удаленного репозитория, но вы можете указать ветвь для извлечения через "hg pull --rev <rev> <url>
" или "hg pull <url>#<rev>
", чтобы получить единственная ветвь. Вы можете указать <rev> используя идентификатор ревизии, имя "named branch" (ветвь, встроенная в журнал изменений) или имя закладки. Однако название закладки (по крайней мере в настоящее время) не передается. Все "названные ветки", которые вы получаете, принадлежат для передачи. "hg pull" хранит концы ветвей, которые он набирал как анонимные, неназванные головы.
В Git по умолчанию (для пула "origin", созданного "git clone", и для пультов, созданных с помощью "git remote add" ) "git fetch
" (или "git fetch <remote>
" ) получает все ветки из удаленного репозитория (из пространства имен refs/heads/
) и сохраняет их в пространстве имен refs/remotes/
. Это означает, например, что ветвь с именем "master" (полное имя: "refs/heads/master" ) в удаленном "источнике" будет сохранена (сохранена) как ветвь удаленного отслеживания "origin/master" (полное имя: "refs/пультов ДУ/происхождение/мастер ').
Вы можете получить отдельную ветвь в Git, используя git fetch <remote> <branch>
- Git, чтобы сохранить запрошенные ветки в FETCH_HEAD, что похоже на несертифицированные главы Mercurial.
Это примеры примеров по умолчанию мощного синтаксиса refspec Git: с помощью refspecs вы можете указать и/или настроить, какие ветки хотите получить, и где их хранить. Например, дефолт "выборки всех ветвей" представлен символом "+ refs/heads/*: refs/remotes/origin/*", а "fetch single branch" является сокращением для "refs/heads/<branch> ::". Refspecs используются для сопоставления имен веток (refs) в удаленном репозитории с локальными именами ссылок. Но вам не нужно знать (многое) о том, что refspecs может эффективно работать с Git (в основном благодаря команде git remote).
Личное мнение: Я лично считаю, что "названные ветки" (с именами веток, встроенными в метаданные изменений) в Mercurial - это ошибочный дизайн с его глобальным пространством имен, особенно для системы управления распределенной версией, Например, допустим случай, когда и у Алисы, и у Боба есть "именованная ветвь" с именем "for-joe" в своих репозиториях, ветки которых не имеют ничего общего. В репозитории Джо, однако, эти две ветки были бы жестоко обращены как одна ветвь. Таким образом, вы каким-то образом придумали соглашение, защищающее конфликты имен веток. Это не проблема с Git, где в ветке репозитория Joe для "joe" из Alice будет "alice/for-joe", а от Bob это будет "bob/for-joe". См. Также Отделив имя ветки от идентификатора ветки, выпущенный на вики-странице Mercurial.
В Mercurial "ветки меток" в настоящее время отсутствует механизм распределения ядра.
Различия:
Эта область является одним из основных различий между Mercurial и Git, как james woodyatt и Стив Лошсказал в своих ответах. Mercurial по умолчанию использует анонимные облегченные коды, которые по своей терминологии называются "головами". Git использует ветки с легкими именами, с инъективным отображением для сопоставления имен веток в удаленном репозитории именам ветвей удаленного отслеживания. Git "заставляет" вас называть ветки (ну, за исключением единственной неназванной ветки, ситуация, называемая отсоединенной HEAD), но я думаю, что это лучше работает с отраслевыми рабочими процессами, такими как рабочий процесс ветки дерева, что означает несколько ветвей в единой парадигме репозитория.
Именование версий
В Git существует много способов переименования версий (описано, например, в Git rev-parse manpage):
- Полное имя объекта SHA1 (40-байтная шестнадцатеричная строка) или подстрока такого, которая уникальна в репозитории
- Символьное имя ссылки, например. 'master' (ссылаясь на ветвь master) или 'v1.5.0' (ссылаясь на тег) или 'origin/next' (ссылаясь на ветвь удаленного отслеживания)
- Суффикс
^
для параметра ревизии означает первый родитель объекта фиксации,^n
означает n-й родительский элемент слияния. Суффикс~n
для параметра ревизии означает n-й предок фиксации в прямой строке первого родителя. Эти суффиксы могут быть объединены, чтобы сформировать спецификатор ревизии по пути от символьной ссылки, например. 'Пу ~ 3 ^ 2 ~ 3' - Вывод "git описать", т.е. ближайший тег, необязательно сопровождаемый тире и количеством коммитов, за которым следует тире, "g" и сокращенное имя объекта, например "v1.6.5.1-75-g5bf8097'.
Существуют также спецификаторы пересмотра, содержащие reflog, не упомянутые здесь. В Git каждый объект, будь то фиксация, тег, дерево или blob, имеет свой идентификатор SHA-1; существует специальный синтаксис, например, например. 'next: Documentation' или 'next: README', чтобы ссылаться на дерево (каталог) или blob (содержимое файла) в указанной версии.
Mercurial также имеет множество способов присвоения имен наборов изменений (описанных в hg manpage):
- Простое целое число рассматривается как номер ревизии. Необходимо помнить, что номера ревизий являются локальными для данного репозитория; в другом репозитории они могут быть разными.
- Отрицательные целые числа рассматриваются как последовательные смещения от вершины, причем -1 обозначает наконечник, -2 обозначает ревизию до наконечника и т.д. Они также локальны для репозитория.
- Уникальный идентификатор ревизии (40-значная шестнадцатеричная строка) или его уникальный префикс.
- Имя тега (символическое имя, связанное с данной ревизией) или имя закладки (с расширением: символическое имя, связанное с данным заголовком, локально в репозиторий) или "именованная ветвь" (фиксация метки, ревизия, заданная "named ветвь" является подсказкой (бездетным фиксацией) всех коммитов с заданной меткой фиксации с наибольшим номером ревизии, если имеется более одного такого кончика)
- Зарезервированное имя "tip" - это специальный тег, который всегда идентифицирует самую последнюю версию.
- Зарезервированное имя "null" указывает на нулевую ревизию.
- Зарезервированное имя "." указывает родительский рабочий каталог.
Различия
Как вы можете видеть, сравнивая приведенные выше списки, Mercurial предлагает номера версий, локальные в репозитории, а Git - нет. С другой стороны, Mercurial предлагает относительные смещения только от "tip" (текущая ветвь), которые являются локальными для репозитория (по крайней мере, без ParentrevspecExtension), а Git позволяет указать любое фиксацию, следующее из любого подсказки.
Самая последняя ревизия называется HEAD в Git и "tip" в Mercurial; нет нулевой версии в Git. Как Mercurial, так и Git могут иметь много корней (может иметь более одного безпорогового коммита, что обычно является результатом объединения ранее отдельных проектов).
См. также: Много разных спецификаций ревизий статья об блоге Илии (newren's).
Личное мнение:Я думаю, что номера ревизий переоценены (по крайней мере, для распределенной разработки и/или нелинейной/веткистой истории). Во-первых, для системы управления распределенной версией они должны быть либо локальными в репозитории, либо требовать обработки некоторого репозитория особым образом в качестве центрального центра нумерации. Во-вторых, более крупные проекты с более длинной историей могут иметь количество ревизий в 5-значном диапазоне, поэтому они предлагают лишь небольшое преимущество перед сокращенными идентификаторами ревизии 6-7 символов и подразумевают строгий порядок, в то время как изменения только частично упорядочены (я имею в виду здесь, что ревизии n и n + 1 не должны быть родительскими и дочерними).
Диапазоны изменений
В Git диапазоны ревизий топологические. Обычно рассматриваемый синтаксис A..B
, который для линейной истории означает диапазон изменения, начинающийся с A (но исключая A) и заканчивающийся на B (т.е. диапазон открыт снизу), является сокращением ( "синтаксический сахар" ) для ^A B
, который для команд перемещения истории означает, что все коммиты достижимы из B, за исключением тех, которые достижимы из A. Это означает, что поведение диапазона A..B
вполне предсказуемо (и весьма полезно), даже если A не является предком B: A..B
означает, что диапазон изменений от общего предка A и B (базы слияния) до версии B.
В диапазонах меркурийного пересмотра используется диапазон номеров версий. Диапазон задается с использованием синтаксиса A:B
, а вопреки диапазону Git действует как закрытый интервал. Также диапазон B: A - это диапазон A: B в обратном порядке, чего нет в Git (но см. Ниже примечание в синтаксисе A...B
). Но такая простота приходит с ценой: диапазон пересмотра A: B имеет смысл только в том случае, если A является предком B или наоборот, то есть с линейной историей; в противном случае (я предполагаю, что) диапазон непредсказуем, и результат локален в репозитории (поскольку номера версий являются локальными для репозитория).
Это исправлено с Mercurial 1.6, который имеет новый диапазон топологической ревизии, где "A..B" (или "A:: B" ) понимается как набор наборов изменений, которые оба потомки X и предки Y. Это, я думаю, эквивалентно "-ancestry-path A..B" в Git.
Git также имеет обозначение A...B
для симметричной разности ревизий; это означает A B --not $(git merge-base A B)
, что означает, что все коммиты достижимы из A или B, но исключая все коммиты, достижимые из обоих из них (достижимые от общих предков).
переименовывает
Mercurial использует переименование отслеживания для обработки переименований файлов. Это означает, что информация о том, что файл был переименован, сохраняется в момент фиксации; в Mercurial эта информация сохраняется в форме "расширенный diff" в метаданных filelog (файл revlog). Следствием этого является то, что вы должны использовать hg rename
/hg mv
... или вам нужно помнить о запуске hg addremove
для обнаружения переименования на основе сходства.
Git уникален среди систем управления версиями тем, что использует обнаружение переименования для обработки переименований файлов. Это означает, что тот факт, что файл был переименован, обнаруживается в момент его необходимости: при выполнении слияния или при отображении diff (если запрошено/настроено). Это имеет то преимущество, что алгоритм обнаружения переименования может быть улучшен и не заморожен во время фиксации.
Оба Git и Mercurial требуют использования опции --follow
для просмотра переименований при показе истории одного файла. Оба могут следовать переименованиям при отображении линейной истории файла в git blame
/hg annotate
.
В Git команда git blame
может следить за движением кода, а также перемещать (или копировать) код из одного файла в другой, даже если перемещение кода не является частью переименования полезного файла. Насколько мне известно, эта функция уникальна для Git (на момент написания статьи, октябрь 2009 г.).
Сетевые протоколы
Оба Mercurial и Git имеют поддержку для извлечения и пересылки в репозитории в той же файловой системе, где URL-адрес репозитория - это просто путь к файловой системе в репозиторий. Оба они также поддерживают выборку из файлов пакетов.
Меркуриальная поддержка получения и нажатия через SSH и протоколы HTTP. Для SSH вам нужна доступная учетная запись оболочки на конечном компьютере и копия hg, установленная/доступная. Для HTTP-доступа требуется выполнение hg-serve
или Mercurial CGI script, а Mercurial необходимо установить на серверной машине.
Git поддерживает два типа протоколов, используемых для доступа к удаленному репозиторию:
- "умные" протоколы, которые включают доступ через SSH и через пользовательский протокол git://(через
git-daemon
), требуют наличия на сервере Git. Обмен в этих протоколах состоит из клиента и сервера, которые ведут переговоры о том, какие у них есть общие объекты, а затем генерируют и отправляют пакетный файл. Современный Git включает поддержку "умного" протокола HTTP. - "немые" протоколы, которые включают HTTP и FTP (только для извлечения) и HTTPS (для pushing через WebDAV), не требуют Git, установленных на сервере, но они требуют, чтобы в репозитории содержалась дополнительная информация, сгенерированная
git update-server-info
(обычно выполняется с крючка). Обмен состоит из того, что клиент идет по цепочке фиксации и загружает свободные объекты и файлы packfiles по мере необходимости. Недостатком является то, что он загружает больше, чем строго требуется (например, в случае с коротким корпусом, когда есть только один пакетный файл, он будет загружаться целиком даже при извлечении только нескольких версий), и для его завершения может потребоваться много соединений.
Расширение: возможность сценариев и расширений (плагинов)
Mercurial реализован в Python, с некоторым кодом ядра, написанным на C для производительности. Он предоставляет API для написания расширений (плагинов) как способ добавления дополнительных функций. Некоторые функции, такие как "ветки закладки" или подписи ревизий, предоставляются в расширениях, распространяемых с Mercurial, и требуют включения их.
Git реализован в C, Perl и сценариях оболочки. Git предоставляет множество команд низкого уровня (сантехника), подходящих для использования в скриптах. Обычный способ введения новой функции - записать ее как Perl или shell script, а когда пользовательский интерфейс стабилизирует переписывание в C для производительности, переносимости и в случае оболочки script, избегая угловых случаев (эта процедура называется builtinification).
Git полагается и строится вокруг [репозитория] форматов и [сетевых] протоколов. Вместо языковых привязок есть (частичная или полная) повторная реализация Git на других языках (некоторые из них частично переопределяются и частично обертываются вокруг команд Git): JGit (Java, используемый EGit, Eclipse Git Plugin), Grit (Ruby), Dulwich (Python), git # (С#).
TL; DR