想象这样一个场景:你和团队正在协作开发一个复杂的软件项目,许多人同时贡献代码、进行修改与增强。没有 一套清晰的变更管理机制,你们就有可能相互覆盖彼此的工作,弄不清是谁在何时因为什么原因做了哪些修改。没有 清晰的方式给"一组更改"打上标签,一旦出现问题,你们就无法快速回退到团队代码的某个稳定版本。没有 明确的工作流与结构化的访问控制,任何人可以在任何时间修改任何东西而无人把关。没有可追溯性控制,你们也无法在需要复现某个发布版本时,确定当时到底是哪些代码文件被用于构建。
再想象另一种情况:好几个团队为一个新应用工作了数月,现在接近上线到生产环境。各种临时 修复与微调已在多个开发与 QA 环境中实施,但它们并未稳定、可靠地反映到生产环境。某些生产 配置没有在 QA 环境中复现,而开发环境之间的差异又很大。随着所需环境的复杂性不断提升,新环境的创建变得耗时且易出错,造成挫败与延误。
这些情形往往导致功能紊乱与精力浪费。源代码管理(SCM) 的实践正是为解决这些问题而生。从本质上说,SCM 是在时间维度上跟踪与管理对代码及其他关键资源(例如配置)所做的变更。
今天,人工智能 正在重塑我们处理 SCM 的方式。AI 可以自动检测风险变更,给出代码或配置的改进建议,甚至通过理解修改意图来帮助解决合并冲突。它还能识别不同环境间的不一致、提出修正方案,并优化部署工作流。AI 驱动的工具不仅帮助团队管理复杂度,更在提速、更安全、更具韧性 的开发周期中发挥关键作用。随着软件交付日益分布化与动态化,AI 正成为让 SCM 更智能、更前瞻、更高效的必备伙伴。
源代码管理简介
团队协同变更的难题可以追溯到编程的早期,SCM 的发展史与计算机编程的演进紧密相连。本节将回顾 SCM 的演化,以及 AI 工具在现代 SCM 中扮演的关键角色。
源代码管理简史
在编程早期,程序相对简单,受限于硬件能力,代码管理也很原始。随着 CPU 更强大、计算与代码愈发复杂,代码仓库 (提供基本 SCM 功能的中央存储)在 1970 年代伴随高级语言与结构化编程兴起而出现。诸如 SCCS(Source Code Control System) 等工具提供了基本的版本追踪,让开发者可以回退到先前版本并查看变更历史。这些早期系统反映了向更有组织的开发方式的转变。
随着 1970 年代更为结构化的软件工程团队出现,SCM 进一步发展。RCS(1982) 与 CVS(1986) 等工具引入了对协作至关重要的功能,包括分支,从而支持更复杂的项目管理与协作文化。
1990 年代早期,IBM Rational ClearCase 作为商业 SCM 解决方案面世,强调健壮的配置管理 与流程定制 ,适用于复杂的软件开发环境。随后 Subversion(SVN) 作为另一种集中式 代码仓库逐渐流行,SVN 1.0(2004) 的目标是弥补 CVS 的不足并提供其缺失的特性。
分布式版本控制与 Git
2000 年代初,敏捷方法 与开源 的兴起为软件开发提出了新需求。快速迭代意味着团队需要对日益复杂的代码库拥有更大的灵活性与控制力;团队规模也变大、并且经常地理分散 。Git 由 Linus Torvalds 于 2005 年创建------他需要一套足以管理 Linux 内核庞大代码库的高效系统,而当时现有方案难以胜任。
版本控制系统(VCS) 是跟踪文件随时间变化的核心技术,是任何 SCM 方法的基础。与大多数早期代码仓库不同,Git 是分布式 VCS 。在集中式 VCS 中,所有人都围绕存放在中央服务器(仓库)上的单一副本 展开工作。每个开发者在本地拥有自己的工作副本 ,可以修改它。当开发者提交(commit)更改时,这些更改会立即上传 到中央仓库,其他人即可看到。要获取他人的最新更改,开发者只需从中央仓库更新 本地副本。图 2-1 展示了集中式 VCS 的工作方式。

分布式系统采用不同的方式。在这种模式下,每位开发者都在本机拥有代码库的完整副本 (既包括仓库本身,也包括他们的工作副本)。开发者所做的更改在明确与团队共享 之前,都只存在于其本地副本。共享的方式是将更改**"推送"(push)到中央仓库。同样地,要查看其他开发者的更新,用户需要从中央仓库 "获取"(fetch)**这些更改到自己的本地副本。图 2-2 展示了 Git 的分布式版本控制。

Git 在速度、分布式特性以及强大的分支机制上的专注,使它在多方面成为"游戏规则改变者":
- 分布式让离线工作成为常态
Git 的去中心化设计让开发者无需依赖中央服务器就能在本地高效、独立地提交与管理更改,也就自然支持了离线开发。 - 灵活的分支与合并
Git 的分支系统极其灵活。开发者可以在隔离的分支上开发新功能或修复缺陷,而不影响主干代码。将这些分支合并回主干也顺滑高效,从而鼓励更大胆的试验与快速迭代。 - 轻量且高效,适配大型代码库
Git 擅长处理大型代码库。它主要存储版本之间的差异(而非完整拷贝),因此更快、更省空间,相比传统 SCM 系统更为高效。 - 非线性历史有利于组织治理
不同于一些强制线性历史的系统,Git 允许通过 rebase 等功能改写历史 。这种灵活性有助于保持代码库历史整洁有序。
几年后,第一批被广泛采用的托管式 Git 代码托管平台出现。最受欢迎的 GitHub 于 2008 年 上线。这些平台在 Git 的能力之上,提供友好的 Web 界面 、云端存储 以及协作功能 ,把 Git 从一款强大但偏技术向的工具,转变为人人可用、社交化的软件开发平台,成为现代软件开发流程的基石。
尽管传统的集中式仓库在某些特定场景中仍有遗存与应用,如今 Git 已成主流选择 。根据 2022 年 Stack Overflow 的调查,94% 的整体受访者使用 Git;在使用任何版本控制 的受访者中,98% 使用 Git。基于此,后文将主要聚焦 Git 仓库 的各类实践。
使用 Git 的分支实践(Branching out with Git)
2010 年 ,Gitflow 分支约定出现,通过分支提供开发、功能创建与发布准备之间的清晰分隔。图 2-3 展示了 Gitflow 工作流。
在 Gitflow 工作流中:
- 主代码库位于名为
main
的分支上。该分支通常被视为稳定分支 ,只应包含可用于生产的代码。 - 创建一个新的
develop
分支,作为所有开发工作的持续集成分支。 - 功能开发在独立分支 上进行(feature/ 与 release/ 分支),这些分支都从
develop
分出 。开发者在这些分支上完成新功能与缺陷修复。功能完成并充分测试后,再合并回develop
。 develop
分支作为所有已完成功能的集成点 ,代表下一个发布版本,并持续接收合并而更新。- 当需要发布时,从
develop
创建一个 release 分支 。可在该分支上进行缺陷修复与小幅调整。最终定稿后,将 release 分支合并回main
,形成正式发布 ;同时在main
上创建对应的**标签(tag)**以标记发布版本。

Pull Request (常缩写为 PR )是 Git 版本控制中的核心协作功能,用于代码评审与集成,在 Gitflow 以及其他分支模型中被广泛使用。PR 为开发者提供了一种结构化的方式:在将更改合入主分支之前,先向代码库提出修改并接受他人审查。
Gitflow 对"计划性发布"和"独立的发布分支"的强调,正逐渐受到更新 Git 分支模型的挑战。随着持续集成/持续交付(CI/CD) 的普及,这些新模型更看重更快的部署 与更频繁的更新 。其中,主干开发(Trunk-based Development) 彻底放弃了单独开发分支的概念;相反,功能在经过严格测试后,持续直接集成 到主分支(常称为 "trunk" 或 "main" )。图 2-4 展示了这一模式。

这种精简的做法带来了更快的反馈循环和更迅速的部署,与现代 DevOps 实践高度契合。在这些工作流中,Pull Request 仍然是不可或缺的一环:在合并到主分支之前,通过代码评审来保障代码质量。
GitOps 与源代码管理
我们已经看到,代码仓库如何伴随编程与软件开发实践一同演进,帮助团队在源代码层面高效协作。但部署层面的难题怎么办?如何高效、系统地构建所需环境,并将代码顺畅地部署到生产?
这正是 GitOps 发挥作用的地方。Dev 与 Ops 的结合强调用自动化消除人工错误,确保各环境的一致性,从而实现更快的部署、更高的可靠性与更低的风险。GitOps 指的是在现代"容器优先、云优先"的基础设施中,自动化基础设施供给与配置 的过程。它强调将代码仓库(通常是 Git)作为系统期望状态的唯一事实来源(single source of truth) ,并借助自动化持续地将实际状态 与期望状态对齐。我们可以把以下资源存放到仓库中:
- 基础设施配置
定义环境所需的组件、虚拟机(VM)的类型与数量、存储配置、网络设置与安全策略等。可以包含声明式 与命令式配置,以及部署脚本。 - 环境变量
用于保存密码、API 密钥等不应直接写入代码的敏感信息。IaC(基础设施即代码)工具通常提供安全管理与引用环境变量的机制。 - 其他资源
视环境复杂度而定,仓库还可以存放用于应用部署的容器镜像(例如通过 git-lfs)等。
将仓库作为唯一事实来源后,我们就能充分利用其强大的能力:细粒度的版本追踪与变更历史 、用 Git 工作流 (例如 PR 代码评审)来管理基础设施更新等。良好的基础设施自动化意味着更快的部署、更少的错误与更可靠的环境,每次创建新环境都可"开箱即用"。第 4 章将进一步介绍如何用 GitOps 进行部署。
Monorepo 与远程缓存
第 1 章曾提到微服务的重要性。在微服务体系中,有两种实践能显著提升生产力:单一仓库(monorepo)与远程缓存(remote caching) 。
- 单一仓库(monorepo) 是指用一个版本控制仓库存放多个项目或服务 的代码。在微服务场景下,它能简化协作、梳理依赖管理、支持跨服务的原子更新,并减少版本冲突。
- 远程缓存 指将构建产物(如编译结果、测试结果)存放在远程服务器上。像 Nx 这样的工具会利用远程缓存复用已生成的输出,避免重复构建,从而显著加速开发流程。
二者结合可支持更快、更高效的 CI/CD 流水线 ,并提升整体系统性能。当然,随着项目规模扩大,monorepo 也会带来一定复杂度;而远程缓存若设计不当,可能引发供应商锁定方面的顾虑。
AI 在源代码管理中的应用
AI 工具正在重塑开发者的编码方式。GitHub Copilot、Cursor、Harness AI Code Agent 等助手/代理像智能的结对程序员,基于项目上下文实时给出代码建议;它们甚至可以预测并补全整行乃至整段代码,大幅提升开发效率。
除了代码补全,AI 助手还能:
- 自动生成样板代码结构
- 提出不同的实现思路
- 进行代码讲解与文档生成
- 协助调试与性能优化
AI 原生软件交付 始于AI 原生的 SCM 。AI 与 SCM 的结合远不止补全:在仓库层面,AI 能分析模式、在问题进入生产前提前识别潜在缺陷 ,并依据跨项目的最佳实践建议架构改进 。这种前置性的能力能显著降低技术债,从源头提升代码质量。我们将在本章后续部分继续探讨这些主题。
接下来,我们将说明 SCM 系统如何融入交付流水线 ;在此基础上,讨论为你的团队选择合适 SCM 时应考虑的因素;最后看看现代代码仓库 (包括 AI 的角色)应具备哪些特征,才能简化整个软件开发流水线。
交付流水线中的源代码管理
核心代码仓库 是交付流水线中的关键组件,起到"锚点"的作用。它作为代码的唯一事实来源,确保一致性与可靠性;开发者也持续与之交互,由此触发集成与交付等各类活动。
图 2-5 展示了代码仓库与**持续集成(CI)和持续交付(CD)**之间的关系。

让我们逐步了解典型流水线的三大部分:
代码仓库(Code repository)
开发者围绕代码仓库开展工作:提交更改、创建与合并(或关闭)拉取请求(Pull Request)。
持续集成(Continuous Integration,CI)
持续集成由代码仓库中的特定动作触发。这些触发条件可按需自定义,例如代码提交、打开或关闭拉取请求,或你团队设定的其他事件。CI 通过自动化构建与测试,为开发者提供快速反馈,充当"预警系统",及时暴露潜在缺陷、集成问题,甚至代码风格违规。即时反馈让问题在早期就被修复,避免演变成成本更高的大问题。借助 CI,代码库可持续保持"可部署"状态,为交付流水线的下一步做好准备。
持续交付与部署(Continuous Delivery & Deployment,CD)
持续交付与部署会自动化基础设施的准备与新版本代码向一个或多个预生产环境的部署。通常会在预生产环境中对应用执行多种类型的测试(本书第 4 章将展开)。最终,经由自动或人工的"闸门"决策,软件才会被部署到生产环境(第 8 章将详述)。通过更小更频繁的变更,CD 精简了交付流程,降低发布风险,并提升对用户反馈的响应速度。
许多代码仓库内置密钥泄露检测功能。常见的"密钥/机密"(Secrets)包括:
- API 密钥(API keys) :用于对各类 Web 服务与 API 进行身份验证与授权的唯一标识。
- 访问令牌(Access tokens) :授予应用或资源特定访问权限的临时凭据。
- OAuth 令牌(OAuth tokens) :用于委托授权,使一个应用可代表用户访问另一资源。
- 私钥(Private keys) :非对称加密中用于解密或验证数字签名的保密密钥。
- 用户名与密码(Usernames and passwords) :用于对系统与服务进行基本认证的凭据。
- 数据库连接串(Database connection strings) :建立数据库连接所需的详细信息,通常包含主机名、用户名与密码等敏感数据。
- 云服务连接串(Cloud service connection strings) :连接如 Azure Storage、AWS S3 等云服务的字符串,可能包含访问密钥等敏感信息。
部分代码仓库会在检测到密钥时阻止或警告开发者进行提交/合并。CI 流程同样可参与密钥检测,防止其进入生产环境。理想做法是两者协同使用,以实现更全面的安全防护。
代码仓库的考量
鉴于 SCM 对软件开发的重要性,选择代码仓库往往是团队最先要做的决定之一。"我们把源代码放在哪儿?"这个问题甚至会影响项目能否顺利启动。
首先,仓库必须支持你团队关键的基础操作与开发流程:
- 创建、导入与克隆仓库,并支持分布式离线工作
- 分支与合并,以及符合团队需求的分支规则(例如仅允许特定用户创建/删除分支)
- 创建、评审与合并拉取请求(Pull Request),以及与治理相匹配的 PR 策略(如要求所有变更必须通过 PR、禁止直接提交、设置最少审核人数量)
- 创建与修改标签,并定义标签策略(如强制遵循语义化版本的命名模式)
虽然各家实现细节不同,但这些都是仓库应有的基础能力。
在搭建交付流水线时,团队通常先选定仓库;由于该选择会对后续实现产生深远影响,因此必须确保代码仓库能无缝融入更广泛的生态中。理想的代码仓库应处于一个能提升团队生产力而非增加负担的生态中,同时具备良好的性价比与组织所需的透明度。
完善的集成能力
优秀的 DevOps 生态应提供易用的工具,以及与交付流水线所需各类功能/服务的全面集成。这不同于"东拼西凑"的方案------后者需要开发者手动打通诸多异构工具,既难排障又有安全风险;也不同于臃肿的"全家桶",往往功能过剩且难以配置。
一个顺畅集成的例子是"配置即代码"(Configuration-as-Code):将对交付流水线的更新与项目代码一样,直接在仓库中版本化与追踪。你还可以像开发流程那样,通过 PR 与审批来约束这些变更,提升协同与治理。
再如安全/漏洞扫描:在 PR 上直接展示检测到的漏洞与修复建议,能帮助开发者在上下文中快速理解并修复问题。
AI 驱动的特性
近几年,基于大语言模型的编码助手/代理快速发展,显著提升了开发效率。它们可以自动补全、生成代码、解释代码等。若这些助手与代码仓库深度集成,能以整个代码库为上下文(而非零散片段),其建议会更准确、更贴切。
MCP(Model Context Protocol,模型上下文协议)在此扮演关键角色:它为 AI 模型与代码助手连接各类数据源(包括 Harness Code Repository、GitHub、Git 等仓库)提供了统一标准,免去了自定义集成的繁琐,降低了开发成本并提升效率。
另一个强大的 GenAI 应用是语义搜索:用自然语言搜索整个代码库。比如用"认证是怎么实现的?相关代码在哪?"来提问,而不是只搜"login"或"authenticate"。这对新成员入职、快速理解复杂代码库尤为有用(如 Sourcegraph 的 Cody、Harness Code Repository 等)。
在代码评审方面,DeepCode、Codacy 等工具使用机器学习自动审查代码变更,更高效地发现潜在缺陷、代码味道与规范问题。AI 在 SCM 的其他用法还包括:在提交前自动扫描安全与合规问题并给出修复建议、PR 摘要生成、以及基于仓库等数据源自动生成交付流水线。
需要注意的是,AI 效果高度依赖其训练数据:好的代码让 AI 产出好的建议与评审,反之亦然。
衡量 AI 的实际价值同样重要。Harness Software Engineering Insights 等工具可用于评估使用不同编码助手的开发者生产力,并与未使用助手的开发者对比。
总体而言,AI 驱动的 SCM 能通过更快更可靠的代码生成(训练良好时尤佳)、在源头识别问题从而提升质量、以及提高评审的效率与质量,来加速上市时间并增强团队协作。
通过开源实现效率与透明
DevOps 工具是否开源也是重要考量。开源方案在预算受限时更具性价比,其透明性也有优势。
商用方案通常承诺可靠的服务可用性与专属支持,但企业订阅费用可能对小团队不友好。开源代码库免费可用、透明且由社区驱动,开发者可按需定制;但支持主要依赖社区,无法保证与商业支持同等的响应与等级;此外,开源的透明也意味着潜在漏洞是公开可见的。
"开源核心"(Open Core)方案(如 Harness.io、GitLab)提供折中之道:免费版(功能受限)+ 商业增强。
最后,出于合规或业务连续性考虑,开源软件(OSS)可进行第三方托管(Escrow):即便供应商停业,你仍可获取构建、测试、监控应用与复刻各环境所需的工具与代码。
平台化路径
传统的"拼装式" DevOps 工具链容易造成数据孤岛,阻碍对整个 SDLC 的可见性;单一 DevOps 平台则能提供端到端视图------从仓库中的首次提交到最终部署上生产,都可被跟踪。这有助于识别瓶颈、及早发现问题,并衡量 DevOps 实践的整体效果。完整的审计轨迹还能简化排障并满足合规要求。
统一平台也简化治理并释放智能自动化潜力。在分散工具中推行治理策略既费力又易出错;单一平台能在端到端一致地定义与执行策略,确保代码遵循编码规范、安全实践与内部准则。比如:用组织认可的安全扫描器,在提交前、CI 过程中、CD 过程中都进行扫描;在统一平台上,这样的策略可被封装成模板复用。
此外,平台若能全面理解部署上下文(包括基础设施与配置细节),还可提供更聪明的代码建议,以优化性能与效率------例如基于服务的部署方式提出改进,从而节省时间并提升质量。
访问控制示例
很多团队最初以点状工具拼出交付链路,但这会带来可观的运维开销。以 RBAC 为例,看看一体化交付平台如何简化操作、赋能团队。
多数协作工具都提供基于角色的访问控制。代码仓库要么内置角色,要么既内置又允许自定义。以 GitHub 为例,其内置角色包括 Read、Triage、Write、Maintain、Admin:Read 适用于非代码贡献者,Admin 则拥有完全访问(包含高风险操作)。
RBAC(基于角色的访问控制)以用户、角色、权限为核心:
- 用户(Users):需要访问系统的个体或账号
- 角色(Roles):一组权限的集合,用于授予对特定资源/操作的访问
- 权限(Permissions):最小控制单元,定义可执行的操作(如读/写/删)
用户并非直接被授予权限,而是被分配到一个或多个角色,从而继承这些角色包含的权限。这样无需给每位用户逐项分配权限,极大简化了管理。下图(图 2-6)示意了用户关联到角色、角色再关联到权限的关系。

使用基于角色的访问(RBAC)是一种常见模式,它通过执行"最小权限原则"为用户仅授予完成其职责所需的权限,从而降低管理开销并提升安全性。基于角色的访问还能帮助合规,因为它清晰记录了系统中"谁拥有什么访问权限"。
角色定义:平台化方法
设想一个由多种异构工具拼装的 DevOps 生态:包含 Git 仓库、Jenkins、用于管理 AWS 基础设施的 Terraform、用于配置管理的 Ansible,以及用于采集性能指标的 Datadog。在这样一个系统里,你往往需要在每个系统里分别定义近似的角色,并为同一个人反复赋权。为一位新开发者开通权限,可能要走多步且耗时。我们来看一体化平台如何用"平台化"的方式处理 RBAC。
以 Harness 平台为例,它采用三级分层结构(Scope):Account、Organization(Org)与 Project:
- Account:最高层实体,可对整个平台进行控制并具备全局可见性。
- Organization(组织) :用于把同一业务单元的人员与项目组织在相对独立的层级中;一个组织下可包含多个项目。
- Project(项目) :协作的基本单位,用户在此层面围绕同一任务一起工作。
**Resource Group(资源组)**是定义用户可访问对象范围的 RBAC 组件。对象可以是任意 Harness 资源,例如项目、流水线、连接器、密钥、代理(Delegate)、环境、用户等。将某个资源组分配给用户后,该资源组中定义的访问权限就授予给该用户。资源组可在任一层级(Account/Org/Project)创建。
Role(角色)同样可以在各层级定义。角色与资源组组合使用,形成完整的权限与访问控制集。例如,你可以把 Pipeline Executor(流水线执行者) 角色赋给仅包含"特定流水线"的资源组,而不是赋予对项目中所有流水线的访问。
总结
本章介绍了 SCM------现代软件开发的基石。SCM 解决了团队协作与代码变更随时间演进的管理问题,使团队能够高效协作并有序管理代码演进。
SCM 是 DevOps 与 CI/CD 工作流的核心,随着 AI 原生 SCM 的出现,其角色正在扩展:这些智能系统能够生成、评审、分析并优化代码,通过自动化日常工作、提升准确性与提供洞见来加速开发、改进交付效率。
我们还讨论了如何选择合适的代码仓库,以及统一 DevOps 平台在打造一致工作流与强化治理方面的优势。打好 SCM 基础后,第 3 章将深入 CI,讲解如何通过持续集成自动化构建与单元测试,以确保代码质量与开发速度。