Azure DevOps Services |Azure DevOps Server 2022 - Azure DevOps Server 2019 |TFS 2018
从另一个版本控制系统(如 Subversion (SVN) )迁移到 Git 时,我们通常建议执行“
提示迁移
”,该迁移仅迁移最新版本的存储库内容,而不包括历史记录。 但是,许多人希望执行更高级的迁移,包括历史记录。 本文中提供的指南介绍了
包含历史记录的
迁移。
到 Git 的 SVN 迁移在复杂性上可能会有所不同,具体取决于存储库的旧版本、创建和合并的分支数,以及使用的是常规 SVN 还是像 SVK 这样的近亲关系。
你有一个新的存储库
你有中继、分支和标记目录的标准设置
在以下的情况下,它可能会很复杂:
你的团队执行了许多分支和合并操作
存储库遵循非标准目录设置
目录设置已随时间推移而更改
可通过多种方式从 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/
。
如果使用标准中继、分支、标记布局,只需放置 --stdlayout
。 但是,如果你有不同的内容,则可能需要传递 --trunk
、 --branches
和 --tags
才能找到什么。 例如,如果存储库结构为 trunk/companydir
,并且你对它进行分支而不是中继,则可能需要 --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 > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'
阅读有关 .gitignore 的详细信息: 使用 Git 忽略文件更改
将存储库推送到裸 git 存储库
在此步骤中,你将创建一个裸存储库,使其默认分支与 SVN 的中继分支名称匹配。
创建裸 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
。
主开发分支将命名为“中继”,这与它在 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 分支很容易,但建议先评估以下几点,然后再继续:
如果有功能分支:是否可以等到它们集成到中继后再迁移?
如果有发布分支:保留 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
作者:霍萨姆·卡梅尔、威廉·萨拉扎尔|查找本文的来源并联系 ALM |DevOps Rangers 分支指南
(c) 2017 Microsoft Corporation。 保留所有权利。 本文档“按原样”提供。本文档中表达的信息和视图(包括 URL 和其他 Internet 网站引用)可能会更改,而不通知。 您自行承担其使用风险。
本文档未向您提供任何 Microsoft 产品中任何知识产权的任何合法权利。 可以复制本文档并将其用于进行内部参考。