$pip install mercurial
(Если же у вас ещё нет Python, пора исправить это: скачайте установщик с https://www.python.org/.)
Ну и наконец понадобится сам клиент Mercurial. Если он ещё не установлен — скачайте и установите с http://mercurial.selenic.com/.
Теперь можно отжигать! Всё что потребуется — репозиторий Mercurial с которым вы можете работать. К счастью, подойдёт любой, так что мы воспользуемся репозиторием "привет, мир", используемом для обучения Mercurial’у.
$hg clone http://selenic.com/repo/hello /tmp/hello
Теперь, когда у нас есть подходящий "серверный" репозиторий, мы готовы разобрать типичные приёмы работы с Mercurial. Как вы увидите, эти две системы очень похожи, так что всё пройдёт гладко.
Как и всегда, вначале мы клонируем репозиторий:
$git clone hg::/tmp/hello /tmp/hello-git
$cd /tmp/hello-git
$git log --oneline --graph --decorate
* ac7955c (HEAD, origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master, master) Create a makefile
* 65bb417 Create a standard "hello, world" program
Наверняка вы обратили внимание, что мы использовали обыкновенный git clone. Это потому, что git-remote-hg работает на довольно низком уровне, подобно тому, как в Git реализован HTTP/S протокол (git-remote-hg служит как бы в качестве "помощника" для работы с удалённым репозиторием по новому протоколу (hg), расширяя базовые возможности Git). Подобно Git, Mercurial рассчитан на то, что каждый клиент хранит полную копию репозитория со всей историей, поэтому приведённая выше команда выполняет полное копирование со всей историей. Стоит отметить, что делает она это достаточно быстро.
git log показывает два коммита, на последнюю из которых указывает довольно много ссылок. На самом деле, не все из них реально существуют. Давайте-ка посмотрим, что хранится внутри директории .git:
$tree .git/refs
.git/refs
├── heads
│ └── master
├── hg
│ └── origin
│ ├── bookmarks
│ │ └── master
│ └── branches
│ └── default
├── notes
│ └── hg
├── remotes
│ └── origin
│ └── HEAD
└── tags
9 directories, 5 files
git-remote-hg пытается нивелировать различия между Git и Mercurial, преобразовывая форматы за кулисами. Ссылки на объекты в удалённом репозитории хранятся в директории refs/hg. Например, refs/hg/origin/branches/default — это Git-ссылка, содержащая SHA-1 "ac7955c" — коммит на который ссылается ветка master. Таким образом, директория refs/hg — это что-то типа refs/remotes/origin, с той разницей что здесь же отдельно хранятся Mercurial-закладки и ветки.
Файл notes/hg — отправная точка для выяснения соответствия между хешами коммитов в Git и идентификаторами ревизий в Mercurial. Давайте посмотрим что там:
$cat notes/hg
d4c10386...
$git cat-file -p d4c10386...
tree 1781c96...
author remote-hg <> 1408066400 -0800
committer remote-hg <> 1408066400 -0800
Notes for master
$git ls-tree 1781c96...
100644 blob ac9117f... 65bb417...
100644 blob 485e178... ac7955c...
$git cat-file -p ac9117f
0a04b987be5ae354b710cefeba0e2d9de7ad41a9
Итак, refs/notes/hg указывает на дерево, которое содержит список других объектов и имён. Команда git ls-tree выводит права доступа, тип, хеш и имя файла для содержимого дерева. Наконец, добравшись до первого элемента дерева, мы обнаружим, что это блоб с названием "ac9117f" (SHA-1 коммита, на которую указывает ветка master), содержащий "0a04b98" (идентификатор последней ревизии ветки default в Mercurial).
Всё это немного запутанно, но хорошие новости в том, что, по большому счёту, нам не нужно беспокоится об организации данных в git-remote-hg. В целом, работа с Mercurial сервером не сильно отличается от работы с Git сервером.
Ещё одна вещь, которую следует учитывать: список игнорируемых файлов. Mercurial и Git используют очень похожие механизмы для таких списков, но всё же хранить .gitignore в Mercurial репозитории — не самая удачная идея. К счастью, в Git есть механизм игнорирования специфичных для локальной копии репозитория файлов, а формат списка исключений в Mercurial совместим с Git, так что можно просто скопировать .hgignore кое-куда:
$cp .hgignore .git/info/exclude
Файл .git/info/exclude работает подобно .gitignore, но не фиксируется в истории изменений.
Предположим, вы проделали некую работу, зафиксировали изменения в ветке master и готовы отправить изменения в удалённый репозиторий. Вот как выглядит репозиторий сейчас:
$git log --oneline --graph --decorate
* ba04a2a (HEAD, master) Update makefile
* d25d16f Goodbye
* ac7955c (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Create a makefile
* 65bb417 Create a standard "hello, world" program
Наша ветка master опережает origin/master на два коммита, пока что они есть лишь в локальном репозитории. Давайте посмотрим, вдруг кто-нибудь сделал важные изменения:
Читать дальше