Корзина С Сюрпризами - Сохраняйте Наши Спешки

TLDR: Готово набор скриптов автоматизация миграции репозиториев Bitbucket из Mercurial в Git. Однажды мой любимый хостинг репозитория Bitbucket объявлено о скором прекращении поддержки репозиториев Mercurial в пользу Git, после чего все репозитории Mercurial будут удалены.



Корзина с сюрпризами - сохраняйте наши спешки

У меня есть много частных репозиториев Mercurial на Bitbucket, и я не хотел терять их, как и их историю коммитов.

Переезд на другой хостинг тоже не вариант — я привык к Bitbucket. Сами Bitbucket, как ни странно, не смогли создать конвертер на месте.

Даже пошаговой инструкции по конвертации не написали, отправив всех на форум вашего сообщества - с довольно иезуитской формулировкой (Мы рады поддержать вашу миграцию, а обсуждение доступных вариантов вы можете найти в нашей специальной ветке Сообщества) - мол, мы рады перенести ваши репозитории на Git, и как это сделать - обсудите это сами на форуме.

Однако в том же посте оставили ссылки на пару конвертеров hg-быстрый экспорт И hg-git .

Первый из них — отдельный скрипт на Python, второй — плагин для работы с Git-репозиториями напрямую из Mercurial. Google также нашел ряд примеров того, как другие решили проблему перетаскивания Mercurial под Git: Здесь , Здесь , И Здесь .

Они также использовали либо hg-fast-export, либо hg-git. Второй для меня уже был проверенным решением — раньше я иногда использовал hg-git, когда коммитил на Github из Mercurial — пока не понял, что в Git, как ни странно, лучше коммитить из Git. Поэтому для своих целей я выбрал hg-git. Здесь Вот скрипт Powershell для автоматизации миграции репозитория, который был отправной точкой моего решения, но для Linux мне пришлось переписать его на Bash. Кроме того, исходный сценарий выполняет миграцию только в локальный репозиторий Git, и я добавил возможность отправлять содержимое преобразованного репозитория Git в репозиторий Bitbucket. Вот как выглядит получившийся скрипт:

  
  
   

$ .

/convert_repo.sh lebedevsergey advertisements_parser 2a51eee7ade0 requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 5 changes to 5 files updating to branch default 5 files updated, 0 files merged, 0 files removed, 0 files unresolved Initialized empty Git repository in /home/serge/project/_probes/hg2git/src/advertisements_parser-git/ pushing to .

/advertisements_parser-git searching for changes adding objects added 1 commits with 2 trees and 5 blobs error: Could not remove config section 'remote.origin' Branch master set up to track

Теперь у меня было готовое решение, но оно требовало ручных действий — перед запуском мне пришлось сначала создать Git-репозиторий на Bitbucket, чтобы было куда запихнуть результат. Глядя на свои 100 500 репозиториев, подлежащих конвертации, я понял, что буду обрабатывать их еще долго.

Мне хотелось бы, чтобы скрипт создавал репозитории Git для конвертированных, а ещё лучше — получал список моих репозиториев Mercurial и работал над ним.

Это явно выходило за рамки возможностей чистого Mercurial; для этого требовался функционал самого Bitbucket, а точнее - Битбакет API .

Для работы с Bitbucket API существуют готовые библиотеки для различных языков программирования, в частности для Python — судя по всему официальные SDK (не путать с давно заброшенным Bitbucket, но когда-то не менее официальным) SDK ).

Существуют также клиенты Bitbucket API для Джава , NodeJS И PHP .

Я выбрал последний.

Однако при детальном изучении выяснилось, что в нем не реализовано получение списка пользовательских репозиториев и создание нового репозитория.

К счастью, создатели библиотеки предоставили возможность расширять свои классы, делая защищенными приватные методы, чтобы, унаследовав их клиентский класс API, я мог добавлять свои собственные методы, которые делают то, что мне нужно:

class ExtendedClient extends Client { /** * @return \Bitbucket\Api\Repositories */ public function repositories() { return new ExtendedRepositories($this->getHttpClient()); } } class ExtendedRepositories extends Repositories { public function listWorkspace(string $workspaceName, array $params = []) { $path = $this->buildRepositoriesPath($workspaceName); return $this->get($path, $params); } public function create(string $workspaceName, string $repoName, array $params = []) { $path = $this->buildRepositoriesPath($workspaceName, $repoName); return $this->post($path, $params); } }

После этого я написал пару PHP-скриптов и еще один Bash-скрипт для их запуска, а через час уже мог любоваться усердно работающим на меня компьютером:

Checking repository: mysett Trying to create Git repository: git_mysett Created Git repository: git_mysett 20abecfb36fe applying clone bundle from https://api.media.atlassian.com/file/4d5980dc-148f-400c-97f7-8067506778a5/binaryЭclient=403e8d2f-6661-452a-8307-5c68f82c1a13&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOnsidXJuOmZpbGVzdG9yZTpmaWxE2bUg7aRIzuKbjwOn5SF8IbGEVs33WHDVb-JYto adding changesets adding manifests adding file changes added 27 changesets with 56 changes to 41 files finished applying clone bundle searching for changes no changes found updating to branch default 35 files updated, 0 files merged, 0 files removed, 0 files unresolved Initialized empty Git repository in /home/serge/project/hg2git/src/mysett-git/ pushing to .

/mysett-git searching for changes adding objects added 27 commits with 82 trees and 50 blobs error: Could not remove config section 'remote.origin' Counting objects: 159, done. Delta compression using up to 12 threads. Compressing objects: 100% (133/133), done. Writing objects: 100% (159/159), 12.95 MiB | 7.95 MiB/s, done. Total 159 (delta 0), reused 159 (delta 0) To git@bitbucket. org:lebedevsergey/git_mysett.git * [new branch] master -> master Branch master set up to track remote branch master from origin. Checking repository: jazzz Trying to create Git repository: git_jazzz

В итоге конвертация заняла около часа работы, после чего я сейчас в фоновом режиме просматриваю конвертированные репозитории Git, чтобы убедиться, что ничего не потеряно.

И только после этого я вручную удаляю оригинальные репозитории Mercurial. Конечно, ничто не мешает добавить удаление из репозитория Bitbucket Mercurial после конвертации в скрипт, но, на мой взгляд, это именно тот случай, когда излишняя автоматизация может нанести вред. Доступен готовый набор скриптов автоматизации миграции репозитория.

здесь P.S.: Пользуясь случаем, подниму риторический вопрос: почему Git, который порой работает с довольно неочевидной логикой, настолько популярен, чем гораздо более логичный Mercurial, в котором вы просто коммитите, создаете ветки и, если что, идет не так, откатывать коммиты, не думая о том, что находится под капотом системы контроля версий, и об указателе на Head, а просто делать то, что нужно? На мой взгляд, это несправедливо, потому что очевидное лучше неочевидного, и очень печально, что поддержка Mercurial прекращается со стороны Bitbucket, одного из столпов сопротивления мейнстриму в системах контроля версий.

Теги: #git #Mercurial #BitBucket #atlassian

Вместе с данным постом часто просматривают: