Microsoft AZ-400: 源码控制与仓库管理 — 学习指南
属于 Microsoft DevOps Engineer Expert AZ-400 — 学习指南. 使用经过验证的答案练习: Microsoft 考试中心, 或参加限时模拟考试: ExamRoll.io.
概述
现代 DevOps 实践依赖于可预测、协作式的源代码管理和规范的存储库管理。Azure Repos 和 GitHub 为版本控制、策略实施、协作和安全提供了互补的功能。精通分支策略、拉取请求工作流、权限、钩子、大文件处理、迁移模式、安全扫描和版本控制,对于构建弹性的交付管道和实现可审计性至关重要。其目标不仅是存储代码,更是要创建一个可强制执行的自动化控制体系,它能在不牺牲质量的前提下提升团队的吞吐量。
Azure Repos 和 GitHub 中的源代码管理基础
Azure Repos 支持 Git 和 Team Foundation Version Control (TFVC)。Git 是分布式的,支持本地提交、轻松创建分支和去中心化的工作流。TFVC 是集中式的,具有服务器端版本控制、锁定签出(可选)等功能,非常适合处理包含超大二进制资产的遗留解决方案,或习惯于集中式工作流的团队。新开发项目应默认使用 Git;当增量变更控制和中央权限至关重要且迁移成本过高时,TFVC 仍然是一个可行的选择。
审慎选择分支策略:
- 主干开发 (Trunk-based development) 倾向于使用单一的、长期存在的主分支 (main),以及生命周期极短的特性分支和持续集成。这种方式能加快流动速度,减少合并债务,是拥有强大测试自动化能力的高节奏团队的理想选择。
- GitFlow 使用长期存在的 develop 分支和 main (release) 分支,并配合使用 feature、release 和 hotfix 分支。它适用于有正式发布排期和需要向后移植修复的产品,但会增加协调开销。
- GitHub Flow 是一个简化模型,拥有单一的 main 分支、生命周期短的主题分支、持续部署和频繁发布。它对于持续交付的服务非常有效。
选择 Monorepo(单一存储库)还是 multi-repo(多存储库)主要是一个组织和工具上的决策:
- Monorepo 将许多组件整合在一个存储库中,便于进行原子化的跨服务变更、统一重构和共享工具。但随着历史记录的增长,它可能会给 Git 操作带来压力。缓解技术包括稀疏检出 (sparse checkout)、部分克隆 (partial clone) 以及使用 CI 路径过滤器来限定构建和测试的范围。
- Multi-repo 将所有权、历史记录和权限边界隔离开来,便于独立的版本控制和保留策略。但这会增加跨存储库的协调工作和依赖漂移的风险;子模块或依赖管理器以及发布编排变得至关重要。
通过代码所有权声明,可以更好地进行所有权管理和变更路由。GitHub 的 CODEOWNERS 文件能自动将路径映射到强制性的审查者。在 Azure Repos 中,可以在分支策略中使用基于路径的必需审查者(以及在启用 CODEOWNERS 的地方使用该文件)来将审查请求路由到相应的组件团队。通过分支命名约定、清晰的提交消息(例如,Conventional Commits)和存储库模板来补充所有权管理,以确保一致性。
治理:策略、权限和拉取请求
Azure Repos 中的分支策略用以固化质量门禁:
- 必需的审查者 (Required reviewers) 强制执行最小审查者数量,可以包括特定的个人/组或基于路径的自动审查者。要求解决批注 (Require comment resolution) 以确保在合并前所有实质性反馈都已得到处理。
- 构建验证 (Build validation) 要求在合并前必须有一个或多个 CI 管道成功通过。使用路径过滤器避免不必要的构建,并设置在新更新时自动触发。通过状态策略集成外部检查,例如安全扫描或性能测试。
- 可以对合并策略进行约束:合并(非快进)(Merge (no fast-forward)) 会记录合并历史;压缩合并 (Squash) 将变更压缩为单次提交,保持历史记录的线性;变基并快进 (Rebase and fast-forward) 会在 main 分支上重写主题分支,形成一条直线历史;变基并合并 (Rebase and merge) 会重放提交,在保留独立提交的同时不产生合并提交。应根据审计需求和下游工具来选择合适的策略。
- 额外的检查包括要求关联工作项、最小成功投票数,以及在存在活动批注或待定审查者时阻止合并。
拉取请求 (Pull Request) 协调了代码集成的整个对话过程:
- 草稿 PR (Draft PRs) 标志着工作正在进行中,并在被标记为就绪之前阻止完成。这鼓励了早期反馈,而不会过早触发策略。
- 自动完成 (Auto-complete) 会在所有策略通过后自动合并,减少了协调延迟,加快了流动速度。
- “绕过策略”权限用于紧急情况或自动化账户。应通过“完成拉取请求时绕过策略”权限严格控制此项,并通过审批和变更管理进行审计。
- PR 模板用于规范化上下文信息:测试证据、风险说明、部署步骤和回滚计划。在 Azure Repos 中,将 pull_request_template.md 文件放在存储库根目录或 .azuredevops/ 目录下。提供关于安全、性能和文档的检查清单。
权限和受保护分支是你的最后一道防线:
- 使用 Azure DevOps RBAC 组(项目管理员、参与者、读者)和细粒度的存储库权限(创建分支、创建标签、参与、强制推送、管理权限、绕过策略)。优先对组设置允许/拒绝,而不是针对单个用户。
- 通过禁止强制推送 (Force push) 和删除 (Delete) 来保护 main 和 release 分支,将“参与 (Contribute)”权限限制为仅通过 PR 合并,并启用要求构建和审查的分支策略。考虑使用“锁定 (Lock)”来临时冻结变更。
- 使用分支级别的权限来限制谁可以创建或完成针对敏感分支的 PR,并分离开发人员和发布经理的职责。
自动化、钩子、大文件和安全
Git 钩子在源头加强质量控制:
- 提交前钩子(Pre-commit hooks)在开发者记录提交之前,于本地强制执行代码检查(linting)、格式化、密钥检查和单元测试。应保持其快速和确定性。
- 推送前钩子(Pre-push hooks)会阻止推送未通过集成测试或策略检查的代码。通过工具(例如,适用于 JavaScript 的 Husky)提供团队范围的钩子脚本,并为选择性加入(opt-in)提供文档说明。
- 托管服务中的服务器端钩子有所不同:GitHub 支持服务器 webhook 和必需的状态检查;Azure DevOps Services 不允许自定义服务器端钩子,但支持分支策略、构建验证、服务钩子以及来自外部系统的状态检查。而在 Azure DevOps Server(本地部署版)中,服务器钩子是可用的。
大文件存储(Git LFS)将大型二进制文件存储在 Git 对象数据库之外,以保持仓库的高性能:
- 使用 git lfs track “*.psd” 或针对特定二进制文件类型来跟踪模式。提交 .gitattributes 文件,以确保所有贡献者都能一致地应用 LFS。
- 通过运行带有路径过滤器的 git lfs migrate import 来迁移历史记录,将大型二进制文件重写为指针。与团队协调并暂停推送;谨慎使用强制推送(force-push)并更新克隆仓库。
- 通过避免不必要的 smudging 操作来管理带宽。使用 GIT_LFS_SKIP_SMUDGE=1 并选择性地运行 git lfs fetch/pull。在 CI 中缓存 LFS,并考虑为那些无需存在于 Git 中的二进制文件使用构件仓库(artifact repositories)。
安全保障应采取左移(shift-left)和基于策略的方法:
- GitHub Advanced Security (GHAS) 提供了密钥扫描(包括推送保护)、使用 CodeQL 进行的代码扫描以及依赖项审查功能,用以捕获暴露的凭证、代码漏洞和供应链风险。应将其作为 PR 上的必需检查来强制执行。对于 Azure Repos,可使用 Advanced Security for Azure DevOps 来实现类似的密钥扫描、通过 CodeQL 实现的 SAST 以及依赖项洞察。
- 应配置密钥扫描,以阻止包含高置信度密钥的推送,并向安全响应人员发出警报。支持为组织特定的模式配置自定义检测器。
- CodeQL 代码扫描应在 pull_request 和 schedule 触发器上运行,将 SARIF 结果作为状态检查上传。调整查询包(query packs)以减少噪音,并对关键路径强制执行覆盖。
- 依赖项审查会在 PR 审查期间揭示版本变更和已知的安全通告;可利用此功能来执行修复 SLA 和许可证治理。
迁移、版本控制和发布管理
从 TFVC 迁移到 Git 需要根据风险承受能力选择合适的策略和工具:
- 对于需要深度历史记录和工作项链接的全保真迁移,使用 git-tfs 将 TFVC 路径克隆到 Git,保留变更集并映射用户。按应用程序或分支进行分区,以保持 Git 仓库的可管理性。在迁移期间或之后,使用 LFS 清理大型二进制文件。
- 对于仅迁移当前状态的轻量级迁移,使用 Azure DevOps 导入工具从 TFVC(或其他 Git 主机)创建一个新的 Git 仓库作为种子,并可选择限制历史记录的深度。这可以缩短迁移时间和降低风险,但会牺牲深度的历史粒度。
- 通过迁移标签/标牌、将 TFVC 分支映射到 Git 分支,并保留一个只读的 TFVC 镜像以供审计,来保留可追溯性。通过试点项目进行验证,在切换期间冻结源代码,并运行验证矩阵(构建、测试和部署)。
采用语义化版本控制以提高清晰度和自动化程度:
- 使用 SemVer 2.0.0:MAJOR.MINOR.PATCH,可附带预发布版本(例如 -rc.1)和构建元数据(+build.45)。使用附注标签(git tag -a v1.4.2 -m “Release 1.4.2”)为发布打标签,并为标签签名以供审计。
- 在 CI/CD 中自动提升版本号:
- 使用“约定式提交”(Conventional Commits)和发布工具(如 GitVersion 或 semantic-release)根据提交类型和范围从提交中驱动版本,计算出下一个版本号。
- 自动更新构建号和包版本;如果发生版本漂移或标签冲突,则构建失败。
- 将版本控制与分支策略对齐:
- 主干开发(Trunk-based):main 分支始终可发布;从 main 创建发布标签;仅使用短生命周期的发布分支进行稳定化。
- GitFlow:release/* 分支承载一个冻结的次要版本;从 main 分支创建 hotfix/* 分支用于紧急补丁;合并回 develop 和 main 分支,并在合并完成时打上标签。
- GitHub Flow:在部署时为 main 打标签;使用预发布标签进行金丝雀发布。
将发布自动化与仓库策略集成:要求发布管道构建成功,阻止没有根据提交生成更新日志的合并,并在受监管的环境中要求签名的提交/标签。
实践问题场景
星巴克必须将多个在 TFVC 中管理的遗留应用程序整合到 Azure Repos Git 中,同时为服务和移动应用建立统一的治理、安全扫描和可扩展的工作流。
- 选择分支和仓库拓扑结构
- 操作:采用主干开发模式,为共享库使用单一代码库(monorepo),为独立发布的服务使用少数几个专注的服务仓库。在开发人员入职脚本中为 monorepo 启用稀疏检出(sparse checkout)。
- 原因:主干开发减少了合并债务并加速了集成;monorepo 集中了共享代码并支持原子化重构,而稀疏检出避免了只接触部分代码的团队需要检出完整历史和工作树的开销。
- 在有价值的地方保留历史记录,将 TFVC 项目迁移到 Git
- 操作:使用 git-tfs 迁移主要的 Web 和移动代码库,并保留完整的历史记录,在迁移过程中将大型资产路径映射到 Git LFS。对于小型工具,使用 Azure DevOps 导入工具仅迁移当前状态。
- 原因:git-tfs 为旗舰应用保留了关键的可追溯性;有选择地使用导入工具可以加速低风险迁移并缩短项目周期。
- 建立受保护分支和分支策略
- 操作:保护 main 和 release/* 分支,禁止强制推送/删除(deny Force push/Delete);要求两名审查者、解决所有评论、链接工作项,并通过带路径过滤器的构建验证。将服务仓库的合并方式限制为 Squash,将 monorepo 的合并方式限制为 Rebase 和快进式合并,以保持线性历史。除了一小部分发布工程团队外,禁用“绕过策略”的权限。
- 原因:策略即代码(Policy-as-code)强化了质量门禁和可审计性。合并策略反映了团队偏好:Squash 简化了服务的还原和 cherry-pick 操作;monorepo 中的线性历史加快了
blame和bisect操作。
- 标准化拉取请求(pull request)实践
- 操作:在 .azuredevops/ 目录下添加 pull_request_template.md,包含风险、测试证据、性能影响和回滚等部分。鼓励尽早使用草稿 PR(Draft PRs);在所有 PR 上启用自动完成(Auto-complete)。配置基于路径的必需审查者以模拟代码所有权,并为托管在 GitHub 上的仓库添加 CODEOWNERS 文件。
- 原因:模板提高了审查质量的下限;草稿 PR 促进了早期协作;自动完成消除了空闲等待时间;所有权路由将正确的审查者分配到正确的代码差异上。
- 实施钩子(hooks)和 CI 门禁
- 操作:通过仓库工具分发 pre-commit/pre-push 钩子,以强制执行代码风格检查(linting)、密钥扫描和单元测试;保持执行速度快。使用 Azure Pipelines 构建验证作为规范的强制措施,并添加来自安全扫描器的状态检查。避免使用自定义的服务器端钩子;使用服务钩子通知外部系统。
- 原因:本地钩子可以在不阻塞协作的情况下及早发现问题;在 Azure DevOps 中,服务器端的强制执行最好通过分支策略和状态检查来实现,以确保可靠性和可审计性。
- 使用 Git LFS 管理大型资产
- 操作:使用 git lfs track 跟踪二进制文件模式(图像、设计资产、测试媒体);使用 git lfs migrate import 迁移遗留的二进制文件。配置 CI 设置 GIT_LFS_SKIP_SMUDGE=1 并选择性地获取以减少带宽;在构建代理上缓存 LFS 工件。
- 原因:保持仓库的快速响应,避免过度的网络使用,同时保持可复现的构建。
- 集成 Advanced Security
- 操作:在 GitHub 仓库上启用 GitHub Advanced Security,在 Azure Repos 上启用 Advanced Security for Azure DevOps。开启带推送保护的密钥扫描,在 PR 和夜间构建时运行 CodeQL,并启用依赖项审查检查。对存在高危漏洞的 PR 阻止其完成。
- 原因:将安全性左移,防止凭证泄漏和可利用的模式进入 main 分支,并在审查期间提供可操作的见解。
- 自动化语义化版本控制和打标签
- 操作:在 Azure Pipelines 中使用 GitVersion 根据分支和提交历史计算 SemVer;在发布管道上签名并推送附注标签;从“约定式提交”生成发布说明。仅使用 release/* 分支进行稳定化;从已打标签的 main 分支创建 hotfix。
- 原因:确定性的自动化版本提高了可追溯性和部署的可复现性,签名的标签支持合规性要求。
这一系列步骤降低了迁移风险,强制实施了一致的质量和安全标准,并简化了交付流程——精确地将仓库管理与可扩展的 DevOps 运营对齐。
所有领域 · 使用 Azure Pipelines 的 CI →
练习这些题目 → · 在 ExamRoll.io 上限时练习 →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
通过考试 →