Отказ от ответственности: я использую Git, следую за разработкой Git в списке рассылки git и даже немного помогаю Git (в основном, gitweb). Я знаю Mercurial из документации и некоторых из обсуждения на IRC-канале #revctrl на FreeNode.
Спасибо всем людям на IRC-канале #mercurial, которые предоставили помощь по Mercurial для этой статьи
Резюме
Здесь было бы неплохо иметь некоторый синтаксис для таблицы, что-то вроде PHPMarkdown / MultiMarkdown / Maruku расширение Markdown
- Структура репозитория: Mercurial не допускает слияния осьминогов (с более чем двумя родителями) и не помечает объекты без фиксации.
- Теги: Mercurial использует версионный
.hgtags
файл со специальными правилами для тегов для каждого репозитория, а также имеет поддержку локальных тегов в .hg/localtags
; в Git теги - это ссылки, находящиеся в refs/tags/
пространстве имен, и по умолчанию они автоматически выбираются при извлечении и требуют явного нажатия.
- Ветви: В Mercurial основной рабочий процесс основан на анонимных заголовках ; Git использует легкие именованные ветки и имеет особый вид веток (ветки удаленного отслеживания ), которые следуют за ветками в удаленном хранилище.
- Имена и диапазоны ревизий : Mercurial предоставляет номера ревизий , локальные для репозитория, и основывает относительные ревизии (считая от наконечника, то есть текущей ветви) и диапазоны ревизий на этой локальной нумерации; 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 (насколько я понимаю) хранит историю файла в файле журнала (вместе, я думаю, вместе с дополнительными метаданными, такими как отслеживание переименования, и некоторой вспомогательной информацией); он использует плоскую структуру, называемую манифестом, для хранения структуры каталогов, и структуру, называемую журналом изменений, в которой хранится информация о наборах изменений (ревизиях), включая сообщение о фиксации и ноль, один или два родителя.
Mercurial использует журнал транзакций для обеспечения атомарности операций и использует усечение файлов для очистки после неудачной или прерванной операции. Revlogs только для добавления.
Рассматривая структуру хранилища в Git по сравнению с Mercurial, можно увидеть, что Git больше похож на объектную базу данных (или файловую систему с адресным содержимым), а Mercurial больше похож на традиционную реляционную базу данных с фиксированным полем.
Различия:
в Git объекты дерева образуют иерархическую структуру; В Mercurial файл манифеста имеет плоскую структуру. В объекте Git blob хранят одну версию содержимого файла; в Mercurial filelog хранит всю историю одного файла. (если не учитывать здесь любые сложности с переименованиями). Это означает, что есть разные области операций, где Git будет быстрее, чем Mercurial, все остальные вещи считаются равными (например, слияния или отображение истории проекта), и области, где Mercurial будет быстрее, чем Git (например, применение исправлений или отображение история одного файла).Эта проблема может быть не важна для конечного пользователя.
Из-за структуры с фиксированными записями структуры журнала изменений Mercurial , коммиты в Mercurial могут иметь только до двух родителей ; коммиты в Git могут иметь более двух родителей (так называемое «слияние осьминога»). Хотя вы можете (теоретически) заменить слияние осьминога серией слияний с двумя родителями, это может вызвать сложности при конвертации между репозиториями Mercurial и Git.
Насколько я знаю, у Mercurial нет эквивалента аннотированных тегов (объектов тегов) из Git. Частным случаем аннотированных тегов являются подписанные теги (с подписью PGP / GPG); эквивалент в Mercurial можно сделать с помощью GpgExtension , расширение которого распространяется вместе с Mercurial. Вы не можете пометить объект без фиксации в Mercurial, как вы можете это сделать в Git, но это, я думаю, не очень важно (некоторые репозитории git используют теговый блоб для распространения открытого ключа 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 description".
Git не имеет строгого эквивалента локальных тегов в Mercurial. Тем не менее, лучшие практики git рекомендуют настроить отдельный общедоступный пустой репозиторий, в который вы помещаете готовые изменения и из которого другие клонируют и извлекают. Это означает, что теги (и ветви), которые вы не нажимаете, являются частными для вашего хранилища. С другой стороны, вы также можете использовать пространство имен, отличное от heads
, remotes
или tags
, например, local-tags
для локальных тегов.
Личное мнение: По моему мнению, теги должны находиться вне графика ревизий, поскольку они являются внешними по отношению к нему (они являются указателями на график ревизий). Теги должны быть не версионными, но передаваемыми. Выбор Mercurial использования механизма, аналогичного механизму игнорирования файлов, означает, что он должен или обрабатывать .hgtags
специально (файл в дереве переносим, но обычный он версионен), или иметь теги, которые являются только локальными ( .hg/localtags
не версионными, но непередаваемый).
ветви
В Git локальная ветвь (tip tip или head branch) - это именованная ссылка на коммит, где можно вырастить новые коммиты. Ветвь также может означать активную линию развития, то есть все коммиты, достижимые из кончика ветви. Локальные ветви находятся в refs/heads/
пространстве имен, поэтому, например, полное имя ветви 'master' - 'refs /head / 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/*
отображение означает, что можно найти состояние ветки 'master' ('refs /head / master') в удаленном хранилище в ветке удаленного отслеживания origin / master ('refs / remotes / origin / master').
Mercurial также имеет так называемые именованные ветви , где имя ветви внедряется в коммит (в наборе изменений). Такое имя является глобальным (передается при получении). Эти имена ветвей постоянно записываются как часть метаданных набора изменений. С современным Mercurial вы можете закрыть «именованную ветку» и остановить запись названия ветки. В этом механизме наконечники веток рассчитываются на лету.
По моему мнению, «именованные ветви» Mercurial следует называть коммит-метками , потому что это то, что они есть. Существуют ситуации, когда «именованная ветвь» может иметь несколько подсказок (несколько бездетных коммитов), а также может состоять из нескольких непересекающихся частей графа ревизий.
В Git нет эквивалента этих «встроенных веток» Mercurial; Более того, философия Git заключается в том, что хотя можно сказать, что ветвь включает в себя некоторую фиксацию, это не означает, что коммит принадлежит какой-то ветке.
Обратите внимание, что документация Mercurial по-прежнему предлагает использовать отдельные клоны (отдельные репозитории), по крайней мере, для долгоживущих веток (одна ветвь на рабочий процесс репозитория), то есть ветвление путем клонирования .
Отводы в толкании
Mercurial по умолчанию толкает все головы . Если вы хотите выдвинуть одну ветвь ( одну головку ), вы должны указать ревизию наконечника ветви, которую вы хотите подтолкнуть. Вы можете указать подсказку ветки по номеру ревизии (локально для репозитория), по идентификатору ревизии, по имени закладки (локально по отношению к репозиторию, не передается) или по встроенному имени ветки (именованная ветвь).
Насколько я понимаю, если вы отправите ряд ревизий, которые содержат коммиты, помеченные как находящиеся в некоторой «именованной ветви» на языке 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>, используя идентификатор ревизии, имя «именованной ветви» (ветка, встроенная в журнал изменений) или имя закладки. Однако имя закладки (по крайней мере, на данный момент) не передается. Все ревизии «именованных веток», которые вы получаете, принадлежат к переводу. «hg pull» хранит кончики веток, которые он выбирает как анонимные безымянные головы.
В Git по умолчанию (для пульта 'origin', созданного "git clone", и для удаленных, созданных с помощью "git remote add") " git fetch
" (или " git fetch <remote>
"), получает все ветви из удаленного репозитория (из refs/heads/
пространства имен) и сохраняет их в Пространство refs/remotes/
имен. Это означает, например, что ветвь с именем 'master' (полное имя: 'refs /heads / master') в удаленном 'origin' будет сохранена (сохранена) как ветвь удаленного отслеживания 'origin / master' (полное имя: 'refs / пультов ДУ / происхождение / мастер ').
Вы можете получить одну ветку в Git, используя git fetch <remote> <branch>
- Git будет хранить запрошенную ветку (и) в FETCH_HEAD, которая похожа на Mercurial безымянные головы.
Это всего лишь примеры стандартных сценариев мощного синтаксиса refspec Git: с помощью refspecs вы можете указать и / или настроить, какие ветви нужно выбрать, и где их хранить. Например, по умолчанию регистр «извлекать все ветви» представлен символом подстановки «+ refs /heads / *: refs / remotes / origin / *», а «выборка одной ветви» является сокращением для «refs /heads / <branch>:». , Refspecs используются для отображения имен ветвей (refs) в удаленном репозитории на локальные имена refs. Но вам не нужно много знать о refspecs, чтобы иметь возможность эффективно работать с Git (в основном благодаря команде "git remote").
Личное мнение: Лично я считаю, что «именованные ветви» (с именами ветвей, встроенными в метаданные набора изменений) в Mercurial представляют собой неверный дизайн с его глобальным пространством имен, особенно для распределенной системы контроля версий. Например, давайте возьмем случай, когда у Алисы и Боба есть «именованная ветвь» с именем «for-joe» в своих репозиториях, ветвях, которые не имеют ничего общего. Однако в хранилище Джо эти две ветви будут рассматриваться как одна ветвь. Таким образом, вы как-то придумали соглашение, защищающее от столкновений имен веток. Это не проблема с Git, где в репозитории Joe для for-joe ответвление от Алисы будет «alice / for-joe», а от Bob это будет «bob / for-joe».
В «ветках закладок» Mercurial в настоящее время отсутствует встроенный механизм распространения.
Различия:
эта область является одним из основных различий между Mercurial и Git, как сказали Джеймс Вудьятт и Стив Лош в своих ответах. Mercurial, по умолчанию, использует анонимные легкие кодовые строки, которые в его терминологии называются «заголовками». Git использует легкие именованные ветви с инъективным отображением для отображения имен ветвей в удаленном репозитории на имена ветвей удаленного отслеживания. Git «вынуждает» вас называть ветви (ну, за исключением одной безымянной ветви, ситуация, называемая отделенным HEAD), но я думаю, что это лучше работает с тяжелыми ветвями, такими как тематический ветвь, то есть несколько ветвей в одной парадигме репозитория.
Имена ревизий
В Git есть много способов присвоения имен ревизиям (например, описано на странице руководства git rev-parse ):
- Полное имя объекта SHA1 (40-байтовая шестнадцатеричная строка) или его подстрока, которая является уникальной в репозитории.
- Символическое имя ссылки, например, «master» (ссылается на ветку «master»), или «v1.5.0» (ссылается на тег), или «origin / next» (ссылается на ветку удаленного отслеживания)
- Суффикс
^
к параметру ревизии означает первого родителя объекта коммита, ^n
означает n-го родителя коммита слияния. Суффикс ~n
параметра ревизии означает n-го предка коммита в прямой строке первого родителя. Эти суффиксы могут быть объединены, чтобы сформировать спецификатор ревизии, следующий по пути из символической ссылки, например, 'pu ~ 3 ^ 2 ~ 3'
- Вывод «git description», т. Е. Ближайшего тега, за которым, возможно, следует тире и несколько коммитов, за которыми следует тире, «g» и сокращенное имя объекта, например, v1.6.5.1-75- g5bf8097.
Существуют также спецификаторы ревизий, включающие reflog, не упомянутые здесь. В Git каждый объект, будь то коммит, тег, дерево или блоб, имеет свой идентификатор SHA-1; Существует специальный синтаксис, например, «следующий: Документация» или «следующий: README» для ссылки на дерево (каталог) или BLOB-объект (содержимое файла) в указанной ревизии.
В Mercurial также есть много способов именования наборов изменений (описанных, например, в hg manpage):
- Простое целое число рассматривается как номер редакции. Необходимо помнить, что номера ревизий являются локальными для данного репозитория ; в другом хранилище они могут быть разными.
- Отрицательные целые числа обрабатываются как последовательные смещения от наконечника, где -1 обозначает наконечник, -2 обозначает исправление до наконечника и так далее. Они также локальны для хранилища.
- Уникальный идентификатор ревизии (40-значная шестнадцатеричная строка) или его уникальный префикс.
- Имя тега (символическое имя, связанное с данной ревизией), или имя закладки (с расширением: символическое имя, связанное с данным заголовком, локальное для репозитория), или «именованная ветвь» (метка коммита; ревизия, заданная «именованной ветвью», tip (бездетная фиксация) всех коммитов с данным ярлыком коммитов, с наибольшим номером ревизии, если таких подсказок более одного)
- Зарезервированное имя «tip» - это специальный тег, который всегда идентифицирует самую последнюю редакцию.
- Зарезервированное имя «ноль» указывает на нулевую ревизию.
- Зарезервированное имя "." указывает на рабочий каталог родителя.
Различия
Как вы можете видеть, сравнивая приведенные выше списки, Mercurial предлагает номера ревизий, локальные для репозитория, а Git - нет. С другой стороны, Mercurial предлагает относительные смещения только от 'tip' (текущей ветви), которые являются локальными для репозитория (по крайней мере, без ParentrevspecExtension ), в то время как Git позволяет указать любой коммит, следующий из любой подсказки.
Самая последняя редакция называется HEAD в Git и «tip» в Mercurial; в Git нет нулевой ревизии. И у Mercurial, и у Git может быть много root (может быть несколько коммитов без родителей; обычно это результат присоединения ранее отдельных проектов).
Читайте также: Много разных статей о спецификациях ревизий в блоге Элайджи (для новичков).
Личное мнение: я думаю, что номера ревизий переоценены (по крайней мере, для распределенной разработки и / или нелинейной / ветвистой истории). Во-первых, для распределенной системы контроля версий они должны быть либо локальными по отношению к репозиторию, либо требовать особого подхода к некоторому репозиторию в качестве центрального органа нумерации. Во-вторых, более крупные проекты с более длинной историей могут иметь количество ревизий в диапазоне 5 цифр, поэтому они предлагают лишь незначительное преимущество по сравнению с сокращенными до 6-7 символьными идентификаторами ревизий и подразумевают строгое упорядочение, в то время как ревизии упорядочены только частично (я имею в виду, что ревизии n и n + 1 не обязательно должны быть родительскими и дочерними).
Ревизионные диапазоны
В Git диапазоны ревизий являются топологическими . Обычно встречающийся A..B
синтаксис, который для линейной истории означает диапазон ревизий, начинающийся с A (но исключая A) и заканчивающийся на B (т. Е. Диапазон открыт снизу ), является условным ^A B
обозначением («синтаксический сахар»), для которого команды обхода истории означают все Коммиты, достижимые из B, исключая те, которые достижимы из A. Это означает, что поведение A..B
диапазона полностью предсказуемо (и весьма полезно), даже если A не является предком B: A..B
означает, что диапазон ревизий от общего предка A и B (объединение базы ) в редакцию Б.
В Mercurial диапазоны редакций основаны на диапазоне номеров редакций . Диапазон указывается с использованием 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 эта информация сохраняется в виде «расширенной разницы» в метаданных filelog (file revlog). Следствием этого является то, что вы должны использовать hg rename
/ hg mv
... или вы должны помнить, чтобы запустить, hg addremove
чтобы сделать обнаружение переименования на основе сходства.
Git является уникальным среди систем контроля версий в том, что он использует обнаружение переименования для обработки переименований файлов. Это означает, что тот факт, что файл был переименован, обнаруживается в тот момент, когда это необходимо: при выполнении слияния или при отображении diff (если запрошено / настроено). Это имеет то преимущество, что алгоритм обнаружения переименования может быть улучшен и не замораживается во время фиксации.
И Git, и Mercurial требуют использования --follow
опции для отслеживания переименований при отображении истории одного файла. Оба могут следовать за переименованиями при отображении построчной истории файла в git blame
/ hg annotate
.
В Git git blame
команда может следить за перемещением кода, а также перемещать (или копировать) код из одного файла в другой, даже если перемещение кода не является частью правильного переименования файлов. Насколько я знаю, эта функция уникальна для Git (на момент написания, октябрь 2009 г.).
Сетевые протоколы
И Mercurial, и Git поддерживают выборку и передачу в репозитории в одной и той же файловой системе, где URL-адрес репозитория - это просто путь файловой системы к репозиторию. Оба также поддерживают выборку из комплекта файлов .
Mercurial поддерживает выборку и передачу по SSH и HTTP протоколам. Для SSH требуется доступная учетная запись оболочки на конечном компьютере и копия hg, установленная / доступная. Для доступа по HTTP hg-serve
требуется запуск скрипта или Mercurial CGI, и Mercurial должен быть установлен на сервере.
Git поддерживает два вида протоколов, используемых для доступа к удаленному репозиторию:
- «умные» протоколы , которые включают доступ через SSH и через собственный протокол git: // (by
git-daemon
), требуют наличия git, установленного на сервере. Обмен в этих протоколах состоит из согласования клиентом и сервером того, что у них общего, а затем генерации и отправки файла пакета. Modern Git включает поддержку «умного» протокола HTTP.
- «тупые» протоколы , которые включают HTTP и FTP (только для извлечения) и HTTPS (для передачи через WebDAV), не требуют, чтобы git был установлен на сервере, но они требуют, чтобы хранилище содержало дополнительную информацию, сгенерированную
git update-server-info
(обычно запускаемую из ловушки) ). Обмен состоит из того, что клиент проходит цепочку коммитов и загружает свободные объекты и файлы пакетов по мере необходимости. Недостатком является то, что он загружает больше, чем строго требуется (например, в угловом случае, когда имеется только один пакетный файл, он будет загружен целиком, даже при получении только нескольких ревизий), и что для завершения может потребоваться много соединений.
Расширение: скриптируемость против расширений (плагинов)
Mercurial реализован на Python , а некоторый основной код написан на C для повышения производительности. Он предоставляет API для написания расширений (плагинов) как способ добавления дополнительных функций. Некоторые функции, такие как «ветки закладок» или подписывание ревизий, предоставляются в расширениях, распространяемых с Mercurial, и требуют их включения.
Git реализован на C , Perl и в скриптах оболочки . Git предоставляет много команд низкого уровня ( сантехника ), подходящих для использования в скриптах. Обычный способ введения новой функции - это написать ее как Perl или скрипт оболочки, а когда пользовательский интерфейс стабилизируется, переписать его в C для производительности, переносимости, а в случае сценария оболочки, избегая угловых случаев (эта процедура называется встроенной ).
Git опирается на форматы [репозитория] и [сетевые] протоколы. Вместо языковых привязок есть (частичные или полные) повторные реализации Git на других языках (некоторые из них являются частично повторными реализациями и частично обертывают команды git): JGit (Java, используемый EGit, Eclipse Git Plugin), Grit (Ruby) , Далвич (Python), git # (C #).
TL; DR