将 SVN 项目迁移到 Git - 分支和标签完全错误

时间:2021-02-04 17:26:36

标签: git svn git-svn

我的目标是以单向、一次性迁移的方式将我的 SVN 存储项目迁移到 Git,即一旦完成,我们将使用 Git 并完全转储 SVN。为此,我正在尝试将提交日志从 v35.0 迁移到应用程序的最新版本(当前为 v49.0)。应用解决方案由大约20-30个项目、库、exe等组成...

我的项目在SVN中的结构(和案例)如下:

  • 分支机构
    • 35
    • ...
    • 49
  • 标签
    • 35
      • 35.0
    • ...
    • 47
      • 47.0
      • 47.1
  • 后备箱

还有与 Branches/Tags/Trunk 处于同一级别的其他文件夹,例如FeatureBranches,但它们都可以忽略。

我在我的 SVN 主干文件夹中运行以下命令来为 Git 正确格式化作者:

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt

我在为迁移创建的新空文件夹中的 Git Bash 提示符下运行以下命令:

git svn init --prefix "" --no-metadata --trunk=Trunk --branches=Branches --tags=Tags https://my/svn/project/

[UPDATED 08/02] 然后我编辑 /.git/config 文件并删除分支行并将标签行替换为:

tags = Tags/35/*:refs/remotes/tags/*
tags = Tags/36/*:refs/remotes/tags/*
tags = Tags/37/*:refs/remotes/tags/*
tags = Tags/38/*:refs/remotes/tags/*
tags = Tags/39/*:refs/remotes/tags/*
tags = Tags/40/*:refs/remotes/tags/*
tags = Tags/41/*:refs/remotes/tags/*
tags = Tags/42/*:refs/remotes/tags/*
tags = Tags/43/*:refs/remotes/tags/*
tags = Tags/44/*:refs/remotes/tags/*
tags = Tags/45/*:refs/remotes/tags/*
tags = Tags/45/*:refs/remotes/tags/*
tags = Tags/46/*:refs/remotes/tags/*
tags = Tags/47/*:refs/remotes/tags/*
tags = Tags/48/*:refs/remotes/tags/*
tags = Tags/49/*:refs/remotes/tags/*

然后我运行命令:

git lfs install

然后我将一个 .gitattributes 文件复制到文件夹中,其中包含要跟踪的文件列表,即 Git LFS。我对此进行了多次尝试,因此我从以前的尝试中保存了该文件。我以前使用过 git lfs track 命令。同样,我复制了一个 .gitignore 文件和由之前的命令创建的 author-transform.txt 文件。

接下来我运行:

git svn fetch --log-window-size=5000 -A authors-transform.txt

然后我会离开大约 25 个小时,做其他事情,吃饭、睡觉、更多工作等。

然后我运行:

for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do git tag ${t/tags\//} $t && git branch -D -r $t; done
for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do git branch $b refs/remotes/$b && git branch -D -r $b; done
for p in $(git for-each-ref --format='%(refname:short)' | grep @); do git branch -D $p; done
git branch -d trunk

上面的最终命令导致:

<块引用>

致命:无法查找 HEAD 的提交对象

[更新 08/02] 我启动 SourceTree 并将其指向我的文件夹,然后恐怖就展开了。有 1 个分支称为“trunk”,有 50 个标签。只有 1 个 hte 标签是正确的 - 35.0,其余都以解决方案项目文件夹之一命名;有些几乎相同,只是后面有一个@number,即Fubar@1423、Fubar@1568

如果这一切没有发生严重错误,我会运行以下命令来完成:

$ git remote add origin <AzureDevOps git url>
$ git push origin --all
$ git push origin --tags

我是一个相对的 Git 菜鸟,所以一直在从其他同事和 Git 文档中拼凑出一些东西,但我不得不承认我有一个冒名顶替综合症的大案例,在这一点上我完全迷失了。如果有人对我做错的命令或配置有任何想法,以及我应该怎么做才能实现我的目标,我将不胜感激。

2 个答案:

答案 0 :(得分:0)

我不得不承认,你的迁移方法总体上还不错。

但是这个 git-config 部分对我来说立即可疑:

branches = Branches/35/*:refs/remotes/*
branches = Branches/36/*:refs/remotes/*
branches = Branches/37/*:refs/remotes/*
# ...
tags = Tags/35/*:refs/remotes/tags/*
tags = Tags/36/*:refs/remotes/tags/*
tags = Tags/37/*:refs/remotes/tags/*
# ...

假设您有一个类似于此的 svn 树:

https://my/svn/project/
├── Branches
│   ├── 35
│   │   ├── Buzqx
│   │   └── Fubar
│   ├── 36
│   │   ├── Buzqx
│   │   └── Fubar
│   └── 37
│       ├── Buzqx
│       └── Fubar
...

...上面的 git-config 要求映射:

  • Branches/35/Fubarrefs/remotes/Fubar
  • Branches/35/Buzqxrefs/remotes/Buzqx
  • Branches/36/Fubarrefs/remotes/Fubar
  • Branches/36/Buzqxrefs/remotes/Buzqx
  • Branches/37/Fubarrefs/remotes/Fubar
  • Branches/37/Buzqxrefs/remotes/Buzqx
  • 等(标签类似)。

我希望你能看到的结局不会很好。您得到的结果正是您所要求的 :)

尝试重做分支/标签映射,以便没有命名空间冲突

另请参阅 man git-svn 中 CAVEATS 的最后一段:

<块引用>

当使用多个 --branches 或 --tags 时,git svn 不会自动处理名称冲突(例如,如果来自不同路径的两个分支具有相同的名称,或者如果一个分支和一个标签具有相同的名称)。在这些情况下,使用 init 设置您的 Git 存储库,然后在您第一次获取之前,编辑 $GIT_DIR/config 文件,以便分支和标签与不同的名称空间相关联。例如:

branches = stable/*:refs/remotes/svn/stable/*
branches = debug/*:refs/remotes/svn/debug/*

编辑:标签的映射示例

<块引用>

每个标签文件夹都有一个用于发布的子文件夹,例如47/47.0、47/47.1

这将在您初始 git-config 中的 tags 行中正确描述,但让我稍微调整一下,以便您可以更好地了解发生了什么。假设您改用它:

tags = Tags/35/*:refs/remotes/svn-tag-*
tags = Tags/36/*:refs/remotes/svn-tag-*
tags = Tags/37/*:refs/remotes/svn-tag-*
# ...
tags = Tags/49/*:refs/remotes/svn-tag-*

然后,这会将 SVN Tags/47/47.1 映射到名为 svn-tag-47.1 的 Git branch¹
当然,这也会将 SVN Tags/35/35.0 映射到名为 svn-tag-35.0 的 Git 分支,等等。

现在,请注意:您的 /Branches 结构与 /Tags 不同(没有每个版本的子目录!...)但是您的 git-config 映射是相同的。 这就是您遇到问题的原因。

试试这样的:

branches = Branches/49:refs/remotes/latest
branches = Branches/48:refs/remotes/stable
branches = Branches/47:refs/remotes/lastyear-stable
# ...
branches = Branches/35:refs/remotes/pre-eol

#-- or at the very very least (NOT RECOMMENDED):
#branches = Branches/*:refs/remotes/svn-branch-*

¹ svn 标签必须是 git 中的分支,因为它们不像 git 标签那样是不可变的。

答案 1 :(得分:0)

所以我的敌人是打字错误+跳枪。

在我的标签列表中,我重复了以下行两次:

tags = Tags/45/*:refs/remotes/tags/*

在那之后,在 SVN 中创建标签之前,我有以下行:

tags = Tags/45/*:refs/remotes/tags/*

为了使标签例如 47.0 和 47.1 出现在我的 Git UI (SourceTree) 中可折叠的 47 标签下,我更新了配置中使用的上述行:

tags = Tags/47/*:refs/remotes/tags/47/*

以上结合删除主要问题编辑中提到的分支线使我达到了 90%。我最终得到了一个主标签和一个从 35 到 49 的标签(我再次尝试时用 SVN 制作的分支/标签)。我仍然有一堆奇怪的标签,比如 47.1@343,实际上大约有 150 个。然而,由于它是如此接近,我只是删除了那些标签,让 Git 为文件生成标签列表,并将其用作包含一堆“git tag -d”命令的批处理文件的基础。

相关问题