从集中式版本控制迁移到 Git

将团队从集中式版本控制迁移到 Git 不仅需要学习新命令。 为了支持分布式开发,Git 会以不同于集中式版本控制系统的方式存储文件历史记录和分支信息。 规划和实施从集中式版本控制系统到 Git 的成功迁移需了解这些基本差异。

Microsoft 已帮助很多内部团队和客户从集中式版本控制系统迁移到 Git。 此体验基于一贯成功的做法从而生成以下指南。

成功迁移的步骤

若要成功迁移,团队应:

  • 评估当前工具和流程。
  • 选择 Git 分支策略。
  • 确定是否以及如何迁移历史记录。
  • 维护先前的版本控制系统。
  • 从源控制中删除二进制文件、可执行文件和工具。
  • 向团队传授 Git 概念和做法。
  • 测试针对 Git 的迁移。

评估当前工具和流程

更改版本控制系统自然会用新的工具和做法中断现有开发工作流。 这种中断可能是改进 DevOps 流程其他方面的一个机会。

团队应考虑在迁移到新系统时采用以下做法:

  • 持续集成 (CI),每次签入都会触发构建和测试通过。 CI 有助于尽早识别缺陷,并为项目提供强大的安全网。

  • 签入代码前所需的代码评审。 在 Git 分支模型中,拉取请求代码评审是开发流程的一部分。 代码评审是对 CI 工作流的补充。

  • 持续交付 (CD) 以自动执行部署流程。 更改版本控制工具要求部署流程进行更改,因此迁移是采用现代发布管道的大好时机。

选择 Git 分支策略

在迁移代码之前,团队应选择分支策略

在 Git 中,短期主题分支允许开发人员与主分支密切合作并快速集成,从而避免合并问题。 两种常见的主题分支策略为 GitFlow 以及更简单的变体 GitHub Flow

Git 不建议使用长期、隔离的功能分支,因为这些分支往往会延迟合并,直到集成变得十分困难。 通过使用新式 CD 技术(如功能标志),团队可快速将代码集成到主分支中,同时仍将正在进行的功能对用户隐藏,直到这些功能完成开发。

当前采用长期功能分支策略的团队可在迁移到 Git 之前使用功能标志。 使用功能标志可最大程度地减少要迁移的分支数,从而简化迁移。 无论他们使用的是功能分支还是功能标志,团队都应记录旧分支和新 Git 分支之间的映射,以便每个人都了解提交新工作的位置。

决定是否迁移历史记录

团队可能想将其现有源代码历史记录迁移到 Git。 多个工具可声明将所有分支的完整历史记录从集中式工具迁移到 Git。 Git 提交似乎可相对较好地映射到先前版本控制工具使用的变更集或签入模型。

但是,此映射存在一些严重限制。

  • 在大多数集中式版本控制系统中,分支会作为存储库中的文件夹存在。 例如,主分支可能是名为 /trunk 的文件夹,而其他分支则是 /branch/one/branch/two 等文件夹。 在 Git 存储库中,分支包括整个存储库,因此很难进行 1:1 转换。

  • 在某些版本控制系统中,标记标签是一个集合,它可包含树中的各种文件,甚至是不同版本的文件。 在 Git 中,标记是特定时间点整个存储库的快照。 标记无法表示存储库的子集,也无法合并不同版本的文件。

  • 大多数版本控制系统会存储有关文件在各版本之间更改方式的详细信息,包括重命名、取消删除和回滚等细化的更改类型。 Git 将版本存储为整个存储库的快照,而有关文件更改方式的元数据则不可用。

这些差异意味着完整历史记录迁移至少会出现损耗,甚至可能具有误导性。 考虑到损耗、所涉及的工作量以及使用历史记录的相对罕见性,建议大多数团队避免导入历史记录。 相反,团队应执行提示迁移,从而仅将最新分支版本的快照引入 Git。 对于大多数团队来说,最好将时间花在迁移方面,因为这些方面具有更高的投资回报,例如改进流程。

维护旧版本控制系统

在迁移期间和之后,开发人员仍可能需要访问先前的版本控制历史记录。 尽管先前的版本控制历史记录随着时间推移已变得不太相关,但能够参考它依然十分重要。 高度管控的环境可能设有针对版本控制历史记录的特定法律和审核要求。

尤其是对于仅执行提示迁移的团队,强烈建议无限期地维护先前的系统。 迁移后,将旧版本控制系统设置为只读。

大型开发团队和受管控的环境可将指向旧版本控制系统的痕迹导航放入 Git。 举一个简单的例子:在提示迁移之前,在 Git 存储库的根目录中将某一文本文件添加为第一个提交,该文件指向旧版本控制服务器的 URL。 如果很多分支都会迁移,则每个分支中的文本文件应说明这些分支如何从旧系统进行迁移。 对于在迁移项目后开始处理项目且不熟悉旧版本控制系统的开发人员,痕迹导航也很有帮助。

删除二进制文件和工具

Git 的存储模型针对紧凑且高度可压缩的文本文件和源代码的版本控制进行了优化。 二进制文件通常很大,一旦将其添加到存储库,它们就会保留在存储库历史记录中,并在将来的每个克隆中保留。 由于 Git 存储历史记录的方式,开发人员应避免将二进制文件添加到存储库,尤其是非常大或经常更改的二进制文件。 迁移到 Git 是从代码库中删除这些二进制文件的一个机会。

此外,还建议从存储库中排除库、工具和构建输出。 改用 NuGet 等程序包管理系统来管理依赖关系。

图标和插图等资产可能需要与特定版本的源代码保持一致。 小型、不经常更改的资产(如图标)不会导致历史记录膨胀,且可直接将其包含在存储库中。 若要存储大型或频繁更改的资产,请使用 Git 大型文件存储 (LFS) 扩展。 有关在 GitHub 中管理大型文件的详细信息,请参阅管理大型文件。 有关 Azure Repos 的信息,请参阅在 Git 中管理和存储大型文件

提供培训

迁移到 Git 中的最大挑战之一是帮助开发人员了解 Git 存储更改的方式以及提交表单开发历史记录的方式。 只准备将旧命令映射到 Git 命令的备忘单并不足够。 开发人员需在集中式线性模型方面停止考虑版本控制历史记录,而是了解 Git 的历史记录模型和提交图。

人们会以不同的方式学习,因此你应提供多种类型的培训材料。 通过专家讲师进行基于实验室的实时培训对某些人非常有效。 Pro Git 书籍是一个很好的起点,可供在线免费使用。

可用的免费动手培训课程包括:

组织应努力确定团队中的 Git 专家,让他们帮助他人,并鼓励其他团队成员提出问题。

测试迁移

团队更新其流程、分析其代码并训练其成员后,便可迁移源代码。 无论是执行提示迁移还是迁移历史记录,请务必在测试存储库中执行一次或多次测试迁移。 在进行最终迁移之前,请确保:

  • 所有代码文件均会迁移。
  • 所有分支均可用。
  • 存储库中没有孤立的二进制文件。
  • 用户具有提取和推送的适当权限。
  • 构建已成功,且所有测试均已通过。

迁移代码

在非工作时间进行最终迁移,理想情况下,应在存在自然停机情况的里程碑之间。 在冲刺结束时迁移可能会导致在开发人员尝试完成工作时出现问题。 尝试在周末迁移,此时无人需要签入。

规划从旧版本控制系统到 Git 的公司直接转换。 尝试并行运行多个系统意味着开发人员可能不知道在哪里或如何签入。 将旧版本控制系统设置为只读,以帮助避免出现混淆。 如果没有此保护措施,可能需进行包含临时更改的第二次迁移。

实际迁移流程因要迁移的系统而异。 有关从 Team Foundation Version Control 迁移的信息,请参阅从 TFVC 迁移到 Git

迁移核对清单

团队工作流:

  • 确定构建将如何运行。
  • 确定何时运行测试。
  • 制定发布管理流程。
  • 将代码评审变为拉取请求。

分支策略:

  • 选择 Git 分支策略。
  • 记录分支策略、选择原因以及旧分支的映射方式。

历史记录

  • 决定旧版控制继续运行的时长。
  • 确定需迁移的分支。
  • 如果需要,请创建痕迹导航来帮助工程师导航回旧系统。

二进制文件和工具:

  • 确定要从存储库中删除的二进制文件和无差别文件。
  • 确定大型文件的处理方法,如 Git-LFS。
  • 确定交付工具和库的方法,如 NuGet。

培训:

  • 确定培训材料。
  • 规划培训活动、书面材料和视频。
  • 确定要充当本地 Git 专家的团队成员。

代码迁移:

  • 执行多次测试运行以确保迁移顺利进行。
  • 确定并传达直接转换时间。
  • 创建新的 Git 存储库。
  • 将旧系统设置为只读。
  • 首先迁移主分支,然后迁移所有其他所需分支。

后续步骤