hg到git转换和subrepo合并

R..*_*R.. 10 git version-control mercurial mercurial-subrepos

尽管涉及两个子部分,但我认为这是一个综合问题,因为它被分解成部分的方式并不重要.只要最终结果保留了所有有意义的历史记录以及检查,研究和构建/测试历史版本的能力,我就会以不同的方式实现我想要的目标.目标是退出hg和到目前为止使用的subrepo模型,然后转移到git中的统一树,但不会牺牲历史记录.

我开始的是一个Mercurial存储库,它包含一些顶级代码和许多有趣历史所在的子存储库.subrepos有一些分支/合并,但没有什么太疯狂.我想要实现的最终结果是单个git存储库,没有子模块,这样:

  • 对于原始顶级hg repo中的每个提交,都有一个git提交,它会检查完全相同的树,因为您将检查相应的hg提交及其所有引用subrepo提交.

  • 这些对应于连续顶级hg提交的git提交是彼此的后代,其提交对应于其间的所有相关子提交.

我对如何实现这一点的基本思想是迭代所有顶级hg提交,并且对于每个更改的顶级提交.hgsubstate,也迭代从旧修订到子模块的新修订的所有路径(可能涉及分枝).在每一步:

  • 查看顶级和所有子目录的相应hg修订版.
  • 从git索引中删除所有内容.
  • 将从hg检出的所有内容都放到git索引中.
  • 使用git-write-treegit-commit-tree生成具有所需父级的提交,使用来自相应hg提交的authors,date和commit消息.
  • 记录新git commit和hg提交之间的对应关系,以用于生成未来提交的父项.

这有用吗?有没有更好的方法来实现我想要的,也许首先用hg做subrepo崩溃?我不清楚的最重要的事情是如何执行所需的迭代,所以如何实现它的实用建议将是伟大的.

一个额外的约束:原始存储库涉及无法发布的内容(这是git-filter-branch基本转换完成后的额外步骤)所以涉及上传存储库以供第三方处理的解决方案是不可行的.

khr*_*hrm 7

你所写的内容可能会或可能不会解决问题.但这并不简单.主要问题是您需要按顺序提交,以便您的子目录和主仓库保持一致.我以小规模重新创建了这个问题,并且能够在subrepos之间保持一致性).

我的解决方案

  1. 使用hg convert扩展,我将主repo转换为repo而没有subrepos(和相关信息).

    cd main
    awk '{ print  $1}'  .hgsub | xargs -n 1 echo 'exclude'  > ../filemap
    echo exclude .hgsub >> ../filemap
    echo exclude .hgsubstate >> ../filemap
    cd ..
    hg convert --filemap filemap  main mainConv
    cd mainConv
    hg update
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用--filemap中的重命名转换subrepo.

    cd ..
    echo rename . subRepo > subFileMap
    hg convert --filemap main/subRepo subRepoConv
    cd subRepoConv
    hg update
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将subrepos拉到转换后的主仓库.

    cd ../mainConv
    hg pull -f ../subRepoConv
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在拉动时你会注意到回购中的多个头(因为subrepo有他们自己的头).合并他们:

     hg heads
     hg merge <RevID from subrepo (not main repo)>
     hg ci -mMergeOfSubRepo
    
    Run Code Online (Sandbox Code Playgroud)

你必须为每个subrepo重复3和4.

  1. 但是提交不会被排序.所以按照这里的顺序将它们按顺序放入/sf/answers/1120881821/:

     cd .. 
     hg clone -r 0 mainConv mainOrdered
     cd mainOrdered
     for REV in `hg log -R ../main -r 'sort(1:tip, date)' --template '{rev}\n'`
     do 
              hg pull ../main -r $REV
     done
    
    Run Code Online (Sandbox Code Playgroud)

现在使用http://repo.or.cz/w/fast-export.git将这个有序的mercurial repo转换为git :

cd ..
git clone git://repo.or.cz/fast-export.git
git init mainGit
cd mainGit
../fast-export/hg-fast-export.sh -r ../mainOrdered
git checkout HEAD
Run Code Online (Sandbox Code Playgroud)


Laz*_*ger 2

无关的题外话

我确信,您选择了最糟糕的迁移想法(从 Mercurial 到 Git),但最终这是您的选择和您的责任

移民课程

我对 Git 的了解相当薄弱,因此对于 Mercurial+subrepo -> monolithic Git 我只能这样看到和描述:

Mercurial+subrepo -> 整体 Mercurial -> 整体 Git 存储库

  • 为了将子存储库历史记录与包装存储库历史记录合并,您可以(通过亚历克西斯评论的更正)使用我之前关于转换扩展的问题中的想法
  • 使用 hg-git 可以轻松地将具有额外抛光历史记录的整体 Mercurial 存储库(一个根,没有匿名头,至少没有链接的书签)推送到空的 Git-repo