Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019 | TFS 2018
从另一个版本控制系统(如 Subversion (SVN))迁移到 Git 时,通常建议执行“
提示迁移
”,此操作仅迁移最新版本的存储库内容(不包括历史记录)。 但许多人希望进行更高级的迁移(包括历史记录)。 本文中提供的指南介绍了包含历史记录的迁移。
SVN 迁移到 Git 的复杂性可能会有所不同,具体取决于存储库的新旧、创建和合并的分支数,以及使用的是常规 SVN 还是有紧密关系的如 SVK。
在以下情况下,此迁移会更简单:
有一个新的存储库
有 trunk、分支和标记目录的标准设置
在以下情况下,此迁移会更复杂:
团队执行了大量分支和合并操作
存储库遵循非标准目录设置
目录设置随着时间推移发生了更改
可通过多种方式从 SVN 迁移到 Git。 本文中概述的方法基于使用
git-svn
,此 Git 扩展可用于将 Subversion 存储库签出到本地 Git 存储库,然后将更改从本地 Git 存储库推送回 Subversion 存储库。 这些步骤详细概述了在 Windows 环境中从 SVN 迁移到 Git 的过程,而无需同步回原始 SVN 存储库。 结果将是一个空 Git 存储库,用于与团队的其余人员共享。
在尝试将源代码从集中式版本控制系统迁移到 Git 之前,请确保熟悉集中式版本控制系统和分布式版本控制系统之间的差异,并
计划团队的迁移
。 准备好后,即可开始迁移。
从 SVN 迁移到 Git 的大致工作流如下所示:
准备迁移环境
将源 SVN 存储库转换为本地 Git 存储库
(可选)在开发人员继续使用 SVN 时,将本地 Git 存储库与 SVN 存储库中的任何更改同步
将本地 Git 存储库推送到在 Azure Repos 上托管的远程 Git 存储库
锁定 SVN 存储库,将 SVN 存储库中的任何剩余更改同步到本地 Git 存储库,并将最终更改推送到 Azure Repos 中的远程 Git 存储库
开发人员改用 Git 作为主要源代码管理系统
准备迁移环境
在本地工作站配置迁移环境并安装以下软件:
Subversion
git-svn 实用工具
(属于 Git)
还需要为组织创建 Git 存储库来托管转换后的 SVN 存储库,可以按照
在项目中创建新的 Git 存储库
进行操作
将源 SVN 存储库转换为本地 Git 存储库
此步骤的目标是将源 Subversion 存储库转换为本地的空 Git 存储库。 空 Git 存储库没有可更改文件的本地工作签出,而是只包含存储库的历史记录和有关存储库本身的元数据。 建议采用此格式来使用 Azure Repos 等服务上托管的远程存储库共享 Git 存储库。
空 Git 存储库的结构不同,并且由于它没有工作目录,因此无法直接提交到存储库。
检索所有 Subversion 作者的列表
Subversion 仅使用每次提交的用户名,而 Git 存储真实姓名和电子邮件地址。 默认情况下,git-svn 工具将在作者和电子邮件字段中列出 SVN 用户名。 但是,可以为 SVN 用户创建映射文件及其相应的 Git 名称和电子邮件。
Subversion 用户
Git 用户
若要从本地 Subversion 签出根目录提取所有 SVN 用户的列表,请运行以下 PowerShell 命令:
svn.exe log --quiet | ? { $_ -notlike '-*' } | % { "{0} = {0} <{0}>" -f ($_ -split ' \| ')[1] } | Select-Object -Unique | Sort-Object | Out-File 'authors-transform.txt' -Encoding utf8
此命令将检索所有日志消息、提取用户名、消除任何重复用户名、对用户名进行排序,并将其放入 UTF-8 格式的 authors-transform.txt 文件中。 然后,可以编辑文件中的每一行,以创建 SVN 用户到格式正确的 Git 用户的映射。 例如,可将 jamal = jamal <jamal>
映射到 jamal = Jamal Hartnett <jamal@fabrikam-fiber.com>
。
使用 git-svn 克隆 Subversion 存储库
以下命令将使用在上一步中创建的 authors-transform.txt 文件执行标准 git-svn 转换。 它将 Git 存储库放置在本地计算机的 c:\mytempdir
文件夹中。
git svn clone ["SVN repo URL"] --prefix=svn/ --no-metadata --authors-file "authors-transform.txt" --stdlayout c:\mytempdir
--prefix=svn/
是必需的,否则工具无法从导入的修订中判断 SVN 修订。 建议设置一个前缀(带有尾部斜杠),原因是因为 SVN 跟踪引用将位于 refs/remotes/$prefix/
,这与 Git 自己的远程跟踪分支布局 (refs/remotes/$remote/
) 兼容。
如果要跟踪共享通用存储库的多个项目,设置前缀也很有用。 默认情况下,前缀设置为 origin/
。
如果使用标准 trunk、分支、标记布局,只需使用 --stdlayout
。 但是,如果使用的是其他布局,则可能需要传递 --trunk
、--branches
和 --tags
来找到具体是什么。 例如,如果存储库结构为 trunk/companydir
,并且对存储库使用的是分支而不是 trunk,则可能需要使用 --trunk=trunk/companydir --branches=branches
。
git svn clone ["SVN repo URL"] --prefix=svn/ --no-metadata --trunk=/trunk --branches=/branches --tags=/tags --authors-file "authors-transform.txt" c:\mytempdir
此命令可能需要几分钟到几个小时,具体取决于 SVN 存储库的大小。 完成后,你将实现存储库的 Git 签出。
转换版本控制特定的配置
如果 SVN 存储库使用 svn:ignore 属性,则可以使用以下命令转换为 .gitignore 文件:
cd c:\mytempdir
git svn show-ignore --id=origin/trunk > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'
阅读有关 .gitignore 的更多信息:使用 Git 忽略文件更改
将存储库推送到空 Git 存储库
在此步骤中,你将创建一个空存储库并使其默认分支与 SVN 的 trunk 分支名称相匹配。
创建空 Git 存储库
git init --bare c:\new-bare.git
cd c:\new-bare.git
git symbolic-ref HEAD refs/heads/svn/trunk
将本地 Git 存储库推送到新的空 Git 存储库
cd c:\mytempdir
git remote add bare c:\new-bare.git
git config remote.bare.push refs/remotes/*:refs/heads/*
git push bare
将 trunk
分支重命名为 main
。
主开发分支将命名为“trunk”,与 Subversion 中对应项的名称匹配。 你需要使用以下命令将其重命名为 Git 的标准 main
分支:
cd c:\new-bare.git
git branch -m svn/trunk main
清理分支和标记 git-svn 会将所有 Subversions 标记转换为 Git 中非常简短的分支,格式为“tags/name”。 需要将所有这些分支转换为实际的 Git 标记或将其删除。
cd c:\new-bare.git
git for-each-ref --format='%(refname)' refs/heads/svn/tags | % { $_.Replace('refs/heads/svn/tags/','') } | % { git tag $_ "refs/heads/svn/tags/$_"; git branch -D "svn/tags/$_" }
将所有 SVN 分支创建为适当的 Git 分支
虽然将所有 SVN 分支创建为适当的 Git 分支很容易,但建议先评估以下几点,然后再继续:
如果有功能分支:是否可以等到它们集成到 trunk 再迁移?
如果有发布分支:保留 SVN 进行维护是否有意义? 如果迁移功能分支,是否准备好从 Git 中提供分支维护?
如果仍要迁移现有分支,请运行以下 PowerShell 命令:
git for-each-ref --format='%(refname)' refs/remotes | % { $_.Replace('refs/remotes/','') } | % { git branch "$_" "refs/remotes/$_"; git branch -r -d "$_"; }
此命令可能需要几分钟到几个小时,具体取决于 SVN 存储库的大小。 完成后,你将实现存储库的 Git 签出。
仅迁移特定修订
如果未指定,git-svn clone
会将第一个提交 (r1) 中的所有修订迁移到 HEAD。 如果只需要迁移一组特定的修订,应将 git-svn clone
的命令追加到 -r
选项中。
例如,如果需要从 rev 100 迁移到 HEAD,则命令如下所示:
git svn clone ["SVN repo URL"] --prefix=svn/ --no-metadata --authors-file "authors-transform.txt" --stdlayout c:\mytempdir -r100:HEAD
更新工作流
从集中式版本控制系统迁移到 Git 不仅仅是迁移代码。 团队需要通过培训来了解 Git 与现有版本控制系统的差异,以及这些差异如何影响日常工作。 了解详细信息。
为项目选择正确的版本控制
了解 Git
使用 Git 忽略文件更改
从 TFVC 迁移到 Git
作者:Hosam Kamel 和 William H. Salazar |查找本文来源和联系 ALM | DevOps Rangers 分支指南
(c) 2017 Microsoft Corporation。 保留所有权利。 本文档“按原样”提供。本文档中表达的信息和观点(包括 URL 和其他 Internet 网站引用)如有更改,恕不另行通知。 您自行承担其使用风险。
本文档未向您提供任何 Microsoft 产品中任何知识产权的任何合法权利。 您可为了内部参考目的复制和使用本文档。