惊喜篮-保存我们的推动力

TLDR:制作了一组脚本,用于自动执行Bitbucket存储库从Mercurial到Git的迁移。

一天,我最喜欢的Bitbucket存储库托管服务宣布,它将很快停止支持Git来支持Mercurial存储库,此后将删除所有Mercurial存储库。

图片

我在Bitbucket上有许多私有Mercurial存储库,就像它们的提交历史一样,我不想丢失它们。迁移到另一个主机也不是一个选择-我已经习惯了Bitbucket。奇怪的是,Bitbucket本身无法制造就地转换器。他们甚至没有编写任何逐步转换说明,而是使用耶稣会士的措辞将所有人送去他们社区论坛(我们很高兴为您的迁移提供支持,您可以在我们专用的社区线程中找到有关可用选项的讨论)-他们说我们很高兴将您的存储库移至Git下,以及如何执行-在论坛上自行讨论。但是,在同一篇文章中,他们留下了指向一对hg-fast-exporthg-git转换器的链接

第一个是一个单独的Python脚本,第二个是直接从Mercurial使用Git存储库的插件。 Google还找到了许多其他示例如何解决其他人在Git下拖放Mercurial的任务:lobeholdlo。他们还使用了hg-fast-export或hg-git。第二个对我来说已经是一个行之有效的解决方案-当我从Mercurial提交给Github时,我有时会使用hg-git,直到我意识到在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 

现在我有了一个现成的解决方案,但是它需要手动操作-在启动它之前,有必要首先在Bitbucket上创建一个Git存储库,以便在哪里推送结果。看着我要转换的100,500个存储库,我意识到我会处理很长时间,我希望脚本本身为转换后的存储库创建Git存储库,甚至更好-它会收到我的Mercurial存储库的列表并进行处理。显然,这超出了纯Mercurial的技能,这里需要Bitbucket本身或Bitbucket API的功能

有现成的库可与Bitbucket API配合使用,以用于各种编程语言,尤其是Python-显然是官方SDK(不要与已久的,但曾经在Bitbucket本身上拥有不少官方SDK混淆)。还有用于JavaNodeJSPHP的 Bitbucket API客户端我选择的最后一个。

但是,当对其进行详细研究时,结果发现它并未实现以获取用户存储库列表并创建新的存储库。幸运的是,该库的创建者提供了通过保护私有方法来扩展其类的可能性,以便通过继承其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存储库中添加删除,但是我认为,这就是过度自动化会造成损害的情况。此处提供

了一组用于自动化存储库迁移的现成脚本

借此机会,我将提出一个反问性的问题-为什么Git有时会以一种不太明显的逻辑工作,而比更具逻辑性的Mercurial更受欢迎,在Mercurial中,您只是提交,创建分支,如果出现问题,则回滚提交而无需考虑版本控制系统的功能是什么,以及有关Head的指针,但只是做您需要的事情?在我看来,这是不公平的,因为显而易见的要比不明显的要好,而且令人遗憾的是,Bitcurket是版本控制系统中抵制主流的支柱之一,它停止了支持Mercurial。

All Articles