精华内容
下载资源
问答
  • 2018-12-12 23:33:42

    码云、github、coding

    • coding

    coding提供网站部署,还有开发IDE,不过初步建立,功能有限。

    -github

    github是国外的一个代码仓库,有事网不稳定可能无法访问,不过有很多优秀的源代码

    • 码云

    码云是来自中国的代码仓库,力荐。

    更多相关内容
  • 5000 万行以上大型代码仓库工程实践

    千次阅读 2021-07-27 00:12:02
    作者:marinewu,腾讯 PCG 工程效能平台部专家腾讯 PCG 工程效能平台部自 2020 年开始进行大仓基本能力建设,并在 2021 年与工蜂合作成立了代码大仓研效联合项目组。在此...

    作者:marinewu,腾讯 PCG 工程效能平台部专家

    腾讯 PCG 工程效能平台部自 2020 年开始进行大仓基本能力建设,并在 2021 年与工蜂合作成立了代码大仓研效联合项目组。在此, 我们想分享大仓/单仓踩过的坑。我们认为这些坑是真实存在且很难避免的,不是小马过河。

    单仓并不简单。成功的单仓所带来的效果绝不止简单的代码聚合,但成本是大量的工具支持以及工程实践。单仓像放大镜,可以将优秀的工程实践以极低的成本推广,但同时也会将错误迅速放大。同时,向单仓迁移的过程也有相当程度的风险。本文会详细讨论单仓的益处、挑战,以及我们对挑战的应对之道,以供参考。

    单仓/大仓是什么?

    • 单仓:指Monorepo,或单一仓库,是指将多个项目放在同个仓库中的版本控制策略。单仓在实践中可能有不同规模,如中心级、部门级、BG 级、公司级单仓。业界最著名的单仓是Google 的 google3,除一些开源项目,Google 内其它所有代码都放置于其中,有超过 20 亿行代码和超过 86T 的容量。目前公司内部成功应用的单仓大多在部门级及以下。

    • 大仓:指大型规模的仓库。“大型规模”并没有严格的定义 -- 在本文中,我们将大仓定义为“单机已无法承受其容量的仓库”。一个粗略的估计:大于五千万行代码 或 容量超过 100G 的仓库即为普遍认可的大仓。

    单仓是我们的目的,而大仓则是(终极)单仓的必然结果。

    为什么要发明单仓?

    单仓的设计核心起源于"One Version"的哲学,并内化了规模化的思想。

    Scalability 可规模化

    在软件工程中,我们希望“解决一次,解决全部”。即,任何的一个良好的工程实践,都以自动化、规模化的手段几乎零成本地推广到所有的团队及代码。这样可以减轻开发人员的心智负担,使之将更多的精力放在创造性的工作上。典型的例子包括代码静态检查、自动化测试及持续集成、开发流程标准化、工具统一化等等。

    单仓极大地简化了规模化:当所有代码都放置在一处,并且高度统一,则所有的工具都可以规模化地在单仓上作业。

    Single Source of Truth ->One Version 从单可信源到单一版本

    Single source of truth(SSoT)原则,是指开发人员在任意时间可以确定代码仓库内的哪个分支是唯一可信依赖源(SSoT)。在 CVS 中,单一来源是核心原则;在 DVS 中,如 git,在现代的业界实践中也采取了该原则,即要求永远都只有一条主干,且所有的分支(除了发布分支)最终都会被收拢回主干里。

    单一版本(One Version)则更进一步,是指在任意时间,代码库内的每一份组件、每一个依赖只有一个版本。

    • 对内部库而言,这意味着使用主干开发(见下),并且必须在主干 HEAD 上依赖。这是一个非常强的约束——这意味着除了终端制品,任何一个内部被依赖的库都不能通过分支发布,而必须保持自己在单仓的主干上一直是发布状态。

    • 对外部依赖而言,同一个第三方库在单仓中永远只会引入一个版本。

    不强制 SSoT/One Version 的版本控制策略往往通过制品/版本分支发布。这意味着在整个依赖关系图之上还有一个版本的维度。这也是在开源社区/SDK 发布商通常采用的策略,其根本原因在于并非完全掌握下游用户的情况。这样除了导致较高的维护成本,还会导致依赖关系难以满足(Dependency hell, 依赖地狱)。

    主干开发 Trunk-based development

    基于版本控制的协作模式一般分两种:

    • 分支开发:每个分支对应一个功能,开发者在这个分支上开发,直到最后完成功能后合并回主干。这是现在小仓下的主流模式。

    • 主干开发:每个分支只对应一个简单的修改。每个开发者在分支上完成修改后经过 CR 尽快合入主干。这是在单仓下推荐的开发模式。

    两者的主要区别在于分支存活时间:保持主干始终健康,将所有的 commits 尽快小批量合入的是主干开发;以 feature 为单位,当 feature 完成之后再重新合入的是分支开发。

    虽然听上去差异微小,但从分支开发迁移到主干开发对研发模式的影响深远。请务必确保您的团队深入理解前置需求(挑战)和长期影响(益处)。下文将分别阐述。

    Case: API Deprecation

    考虑以下常见场景:一个公共库的作者如何 deprecate 旧的 API 并提供新的 API 作为替代品?

    小仓场景:这个公共库按版本分支或按制品发布。API 可以在下一个版本直接更新,并强制 API 调用方对 API 进行更新。这样的好处是 API 提供方的责任较简单,坏处是每一个 API 调用方都需要自行更新代码,并且 API 提供方无法保证自己的新版 API 已经被使用。

    单仓/主干场景:公共库只提供源码依赖,并不按版本发布。这样,我们需要保证公共库在主干上始终是正确的。API deprecation 时,API 提供方可以查找所有 API 调用方,并且发动大规模自动修改,原子性地将所有的旧 API 调用更新至新的 API。这样的好处是 API 调用方的责任更简单,但是这种修改只有在能够查找 API 的所有用户、并且整个持续集成水平较高时才有可能。

    从上面的例子可见,在单仓/主干的场景下,很多代码的维护工作可以左移并规模化。减少重复劳动、大规模的工业化,是我们启用单仓的原动力。

    益处

    以下的益处基于开发者视角和代码维护者视角。

    再次提醒, 单仓想要达成预期效果需要工具、流程和文化三方面的准备,以及长期大量持续维护。贸然迁移到大仓不但不会带来收益,反而会导致项目和代码管理彻底混乱。请确保您对挑战部分有所准备。

    主干开发

    主干开发是为了进行持续集成。频繁地、小批量地构建/测试是持续集成的关键。通过主干开发可以:

    • 避免较长的稳定期,使持续集成可以持续运行,均摊每次合入的风险

    • 使不同特性的开发成员可以及早地了解其它团队可能对代码结构的影响

    • 避免合流日必须大量合并冲突的痛苦

    • 降低 CR 的难度和成本:主干开发下每个合入主干的提交更小,而 CR 的难度随提交修改量高于线性增长,因此 CR 的难度均摊更小。另外,强制小批量合入主干的提交可以将 CR 的责任从分支所有者转移到代码所有者,这更利于对代码质量的长期维护。

    更容易的代码复用与分享

    在大仓下,所有的代码会变得更公开透明。这便于我们抽象出共同的需求,建立公共库与公共框架,也便于我们学习更优秀的代码,以及寻求常见问题的解决方案。另外,我们对公共代码的调用可以变得更简单:直接从代码层面依赖,而非必须使用包管理/制品/跨仓库的依赖。

    例子:查询 API 的使用方法

    需要一个调用非常复杂(例如一个有几百个 fields 的 protobuf)的 API。如何才能正常调用?Stackoverflow 里不存在答案,而码客似乎也不适合提问,难道只能找 API 的原作者询问用法?

    如果在大仓中,可以查找该 API 已有的在生产环境中的调用作为极好的参考。相反,在纷乱的小仓,缺少好的代码检索工具,很难确定 API 到底在哪里被调用。

    需要:

    • 工具 编译系统:统一的优雅的编译系统可以降低代码的复用的工作量。

    • 工具 权限控制

    • 工具 代码浏览工具

    开放协作的文化

    大仓模式下会带来/诱发合作模式的改变。我们认为现代软件开发关键在于团队合作,因此一个能够增加透明度、允许更高层面合作的开发模式能够促成更透明更亲密的合作。更进一步,根据Conway's law,一个所有人的代码都公开透明、亲密协作的组织能够产生更加公开透明、结构亲密协作的产品(注意:这里协作不代表耦合)。

    在大仓模式和主干开发的模式下, 我们可以更方便地主动去为其他组的项目提交代码,例如修复缺陷或实现我们所需的新功能。这个组可能是姐妹组,也可能是相隔甚远的项目组。

    我们认为作者对代码有太强的归属感,即有强烈的领地意识,对开放协作文化有害。隐藏代码或不允许别人触碰自己编写的代码是反模式。允许别人修改,自己由 CR 做最终决定,是更为开放和有效的合作模式。

    例子:公共库/框架

    一个公共库/框架的诞生往往通过两种途径 -- 自顶向下和自下向上。自下向上指通过逐步聚合抽象公共需求和组件。例如一个顶目的开发过程中,基于实践抽象出自己项目的公共库;慢慢地,该公共库与其它项目的公共库的共同部分会产生相当程度的重叠,我们便将这部分交集进行整理和泛化,升级为更高级别(如产品线)的公共库。经过更进一步的抽取和整合,最终形成公司级别的公共库。如果没有足够的透明度和协作,这种聚合几乎是天方夜谭。

    需要:

    • 流程·代码评审:开放协作的文化必须要通过严格的流程来制约

    • 流程·结构管理:需要规范来控制大仓的目录结构,否则随意的创建目录会非常快速增加仓库熵以致于不可控

    原子修改 Atomic Commits

    原子修改指我们可以在一个提交中修改在单仓中的多个项目的代码并同时生效。这对仓库始终保持在一致状态至关重要。与此相反,在小仓场景下,我们需要在每个需要修改的仓库发送提交,这意味着原子性不能保证,即我们无法保证这些提交同时生效。

    一个典型的例子是同时修改 API 接口、实现以及所有的 API 调用者。如此,我们就可以避免同时维护同一接口的两个版本。

    注意:原子修改也无法解决 C/S 不统一的问题。即对 API 的更改,即使对实现和调用的更新和 API 更新一起是原子提交,也无法解决 C/S 面对的接口不一致的问题。因为 C/S 的发布周期不会因为原子提交而实现原子化。

    大规模修改 Large Scale Change

    由于开发人员可以访问所有项目,因此我们可以批量地进行大规模的自动化的简单修改,例如 API 更新、自动清理长期未被引用代码等,以维护代码质量。这种由工具团队发起的大规模的修改在大仓开发模式下十分常见。

    需要:

    • 工具·持续集成:只有保证足够高质量和覆盖率的自动化测试、足够优秀的持续集成才能让我们有足够的工程信心进行大规模的修改。

    • 工具·大规模修改:为了能自动化进行大规模修改,需要能够自动按规则大范围修改代码、自动格式化代码的工具。

    代码治理简单

    代码单一的存放位置使得代码作业更加简单。

    例子:代码扫描

    我们希望建立知识库,因此希望扫描所有相关仓库内的 markdown 工程文档。小仓场景下,我们需要维护所有相关仓库的列表,克隆并扫描每个仓库。单仓场景下,只扫描一个仓库即可。

    依赖管理简单

    在大仓里,第二方和第三方依赖可以直接依源码导入,并且只有一个版本。这样可以极大地简化我们对依赖的治理。而且也可以减少已经标准化的项目对引入第三方依赖的成本,因为这些引入的依赖需要标准化,如 Bazel 化。

    注意:第三方依赖的治理本身是需要大量工作的。详见[挑战·依赖管理]。

    挑战

    以下挑战基于单仓维护者视角。

    这些挑战是我们在以往大仓开发/大仓迁移过程中真实踩过的坑,而非臆想。我们鼓励所有考虑迁移单仓的团队在迁移前认真检查自己是否对以下挑战有所了解并做好准备。另外请注意,以下尚未穷举所有挑战,您需要随时准备迎接新的挑战。

    单仓不是银弹。事实上,单仓/主干开发不应该做为一个孤立的工程实践,而更应该被视为一个工程实践的放大器 -- 除了固有的挑战,它可以实现工业化,放大其它的流程/工具的收益;但是如果没有足够有效的工具和严格的流程及实践控制,大仓几乎就是灾难的代名词。下文中“单仓所需的工程实践”并非严格的限制,但这正是陷阱所在 -- 不满足这些前置的单仓还不如小仓。小仓虽然也需要这些实践,但是至少可能不会有这么强的扩散效应。如果妥协,即在单仓内完全采取和小仓一样的严格隔离项目并采取分支发布的策略,则迁移单仓的意义基本被消解。

    我们将挑战分为两类:

    • 单仓:由于多个项目在同个仓库中所带来的治理挑战

    • 大仓:由于仓库的体量导致的可扩容性挑战

    所有大仓引起的挑战在下文有特殊标明。如果您的单仓规模较小可暂时忽略,但请做好仓库规模增长的准备。

    权限控制

    代码迁移到单仓会引入对权限控制的新要求。

    提交权限

    目前我们的提交权限以 Git 仓库为最低颗粒度。在单仓中,仓库级别的权限控制不足以支持多个团队、多个项目在单仓内作业。因此“项目”级别的权限控制是必须的 -- 在单仓场景下,这需要目录作为最小颗粒的权限控制。

    同时,我们不建议照搬小仓的提交权限机制,即“只有目录的 owner 才能在该目录下提交”。我们认为提交权限需要在 CR 层面解决,即并非“只有有权限的人才能提交”,而是“只有有权限的人作为作者,或者作为评审者同意提交,才能提交”。

    我们的实践:

    引入类似于Chromium 的 OWNERS机制。机制的关键在于:

    1. OWNERS,而非 commit 的作者,为代码质量负责。

    2. OWNERS 机制需要具有高度的灵活性。默认,OWNERS 的权限为所在目录树。但是 OWNERS 也可以为文件(per-file)级别提供颗粒度。

    3. OWNERS 的定义不应该在仓库根目录,而应在所在目录。并且,OWNERS 文件应该是可继承的。例如,/foo/bar/...的 OWNERS 应该是:

    我们与此同时将设立一个工具以自动为 commit 自动分配 reviewer,因为在大仓下寻找正确的 reviewer 会相对更困难。

    可见权限

    一个不太常见的、与大仓的设计目的相反的需求是隐藏代码。有一些代码是必须需要维持私密性的,例如与权限相关的代码或者具体高商业价值的代码。所以这些代码需要只对一部分人可见,并需依赖大仓其它代码进行编译。这里有几个选项:

    • 在大仓内提供更细颗粒度(如目录级别)的可见性控制。需要代码托管方的支持。

    • 私密代码放入小仓中,以小仓的权限控制来保证保密性。大仓保持所有代码的可见性。注意:这意味着可能有小仓向大仓的依赖,可能需要版本控制工具的支持对大仓的依赖。

    我们的实践:暂时未遇到,视情况解决。

    清除提交

    一个更加少见的需求是清除一个提交。例如,一个提交泄露了高商业价值信息,需要及时清除。如何从仓库历史里以及从开发者本地的克隆里及时清除是一件困难的事情。在小仓场景下,我们可以简单地将提交所在仓库归档为私有,将该提交之前的所有历史复制到另一个新的仓库,将新的仓库公开并删除旧的仓库。在单仓场景下,其影响面会比原来大。

    我们的实践:暂时未遇到,视情况解决。

    巨大代码存储空间

    大仓需要的存储空间可能会非常大。以 Google 为例,2015 年时已经有 20 亿行代码,仓库超过 86T。这个大小对版本控制造成了非常大的挑战,尤其是默认 Git 会下载整个仓库。这对代码托管方、开发、代码分析方(如 CI/数据分析/...)等原本可以单机承载单仓容量的系统都会造成更大的压力。

    我们的实践:我们与代码托管方,即工蜂,合作成立了代码大仓研效联合项目组,以解决扩容问题。

    可扩容性

    (该部分为大仓引起的挑战。如果您的单仓规模较小可暂时忽略,但请做好仓库规模增长的准备)

    可扩容性的核心挑战在于,如果工具是以仓库为操作单元,则其随开发人员数量的增长往往不是线性的,而是以不低于二次方增长的。举例, 考虑每次持续集成都编译整个仓库,则如果人员增长 10 倍,可以粗略假设仓库大小增长 10 倍,提交频率增长 10 倍,则整个编译量会增加 100 倍。

    我们认为所有的所有开发工具和流程都应该优化,使之随仓库的规模上升线性增长。如果无法保证,请保证您的单仓较小。

    版本控制

    版本控制工具将主要面对两个挑战:

    1. 代码存储空间大

      原生 Git 对仓库的最小操作单位是仓库,即不支持部分检出。这有其设计目的和历史原因,因此原生 Git 并不适合大型仓库。为了缓解这个问题,Git 本身做了很多尝试,如支持 Git-Lfs, Git Submodule, Git sparse checkout, Git partial clone 等,但是更像是在打补丁。

    2. 主干进展迅速

      大仓乃至单仓的提交非常频繁,主干进展很快,因此需要频繁进行 rebase。这对 rebase 的性能有所要求,并且可能需要您提交锁的设计。

    如果使用 Git 作为版本控制工具,在迁移到大仓之前,请确保您对仓库大小有所控制,包括:

    1. 使用 Git-LFS,尽可能地把非代码的大文件,如资源,托管到 LFS。

    2. 定期归档 Git 历史,保持.git 文件大小可控。

    3. 强制采取 Squash and merge 方式合并,保持主干简洁。

    我们的实践:我们对 Git 进行了改造,开发了基于懒加载的检出方案。基于前文所提到的 Code access API,我们实现了对文件的按需检出。在初次 clone 时,所有的文件都只有元数据被下载,只有当需要获取文件内容时才会真正下载文件。

    构建系统

    我们强烈推荐在单仓使用统一的构建系统。至少,每门语言应该使用统一的构建系统。否则,您可能使用的不是一个单仓,而是一个将众多小仓放在一起的空间。

    我们认为一个适合大仓的构建系统应该满足以下要求:

    • 构建可以是局部的。整个大仓应该作为一个方便彼此之间的依赖,但是在构建时应该允许只编译当前感兴趣的模块。

    • 构建可以是增量的。有限的修改应该只触发有限的重建,并且可以保证正确性。

    • 构建的配置应该是显式的、代码化的。理想状态下, 一个 repo + branch + commit + build target 即可以完整地、唯一地确定编译产物。这对 CI/CD 非常重要,即 CI 的正确性可以保证制品的正确性。

    • 依赖关系应该是显式的,包括传递依赖也应该是显式的。这样可以方便我们对系统模块化,并且更好地管理依赖,包括第一方以及第三方依赖。

    一个常见的错误是,把构建速度作为选择构建系统的唯一指标。另外,我们推荐统一每个语言的编译器以及对应版本。

    我们的实践:我们采用Bazel作为唯一的构建系统。Bazel 有以下优点:

    1. Bazel 的编译是局部的。

    2. Bazel 的编译是增量的,并且提供了分布式中间结果缓存以及分布式中间结果构建接口。搭建分布式缓存和分布式构建集群对 Bazel 的编译速度提升效果非常明显。

    3. Bazel 的编译声明是显式的,并且所有的依赖关系也是必须的显式的。

    4. Bazel 是跨语言的:Bazel 的核心是一个构建引擎,所有的语言支持都是以 DSL 的扩展实现的。

    如果要建立单仓,推荐考虑 Bazel 作为构建系统。但是请注意:

    1. Bazel 本身对构建系统需要有较深理解。我们推荐在您的组织内培养一定数量的专家对构建进行维护。

    2. 请不要使用 Bazel 4.0 之前的版本。Bazel 4.0 是第一个 LTS 版本,在此之前的版本 Bug 甚多。另外请尽量只使用 LTS 的版本。

    (大仓体量下的)持续集成

    一个能够支持大仓体量的、可伸缩的持续集成系统是高度不平凡的。在设计持续集成系统,请确保已考虑以下可能需要解决的问题:

    1. 持续集成的自动测试应该测试哪些目标

      a.全量测试:朴素地编译整个大仓里的所有项目、执行所有测试可能并不是一个可行的方案,因为耗时可能过长。

      b.人工精准测试:人为定义一个“项目”,当项目内的文件被修改时,执行所有项目相关的测试。但是该策略可能难以保证所有被影响的目标都会被测试到,尤其当修改的代码是公共库时。

      c.精准测试:从构建系统出发,计算被修改的文件所可能影响到的所有测试。但是这需要构建系统的支持(这也是为什么我们推荐 Bazel 的原因之一)。另外,大型测试,如需要搭起多个服务的系统测试,依然需要一个不基于依赖关系的测试策略,即需要人工精准测试。

    2. 自动构建/测试的体量可能超过单机承载量,即使已经采取了精准测试。您可能需要将测试任务分片。

    3. 持续集成的构建机需要快速拉取代码进行构建和测试。请注意在大仓的体量巨大时,构建机可能每次构建都重新下载整个仓库的代码可能并不可行。您可能需要在构建机上缓存代码或者采取其它的裁剪策略保证您的持续集成不会因为下载代码花费过长时间。

    4. 您可能需要严格执行持续集成的“主干永远是绿的”政策,即,主干上持续集成变红/变黑之后,受影响的团队需要立刻修复问题,或者,无法快速修复时,还原相关修改。

      a.您可能希望通过"PreMR 100%成功"保证主干永远是绿的。遗憾的是,这在大仓中无法做到。由于主干进展很快,我们在执行 PreMR 集成测试时的主干 HEAD 与实际合入时的 HEAD 可能相差甚远,这可能导致中间会由于被依赖文件的修改而发生合入之后的测试失败。因此您始终需要 PostMR,且 PostMR 需要更大范围的测试,因为这种情况只有在 PostMR 的自动化测试才能发现。

      b.您需要对主干上“失败肇因识别(culprit finding)”准备策略。这是指,PostMR 由 commit A 失败的测试(记为 T)未必是由 A 导致的。如果 T 上次测试通过的 commit 是 B,则所有在(B, A]之间的所有 commit 都可能是肇因。您可能需要对所有测试目标一段时间持续集成执行历史的记录。

    5. 并发的执行自动测试的请求可能超过构建机的数量。您可能需要机器锁,或者一个更好的构建队列调度器。当 PreMR 和 PostMR 同时在排队时,您可能会需要给 PreMR 更高的优先度以不阻碍开发人员的工作。

    我们的实践:我们设计了新的持续集成服务。

    质量保证所必需的工程实践

    主干开发

    注意从分支开发到主干开发需要大量的学习成本,不可能一蹴而就。未实操过主干开发的开发者很可能难以想像如何采用这种方式工作。我们推荐进行大量的培训,甚至类似于导师制,来培养团队主干开发的习惯和能力。我们强烈不建议使用考核等行政手段作为唯一的推进手段,因为向主干开发的切换并非只是意愿问题。

    为达成主干开发,除了开发人员的培训,您需要在单仓中以下工具/实践:

    • 小批量开发。

    • 开关系统。当一个特性尚未开发完成,您需要在主干中通过开关将该特性屏蔽,使用户和其它特性完全不受该特性影响。开关系统分为两类:编译时开关和运行时开关, 区分在于开关可以判断状态的阶段。我们推荐:

      • 通过编译时开关进行主干开发协作;

      • 通过运行时开关进行上线发布以及 A/B 实验。这并不局限于大仓。

    • 高优先度的代码评审:相比于开发,CR 的优先应该更高。保持 CR 流程的畅通是主干开发的必要前置。

    • 保持主干健康。当主干上出现了构建/测试失败,需要开发者停止当前工作并立即修复 CI 问题。

    • 持续集成,见下。

    (单仓中的)持续集成

    主干开发和持续集成是相辅相成的关系。尽快往主干的提交使得持续集成可以更细地触发,而持续集成是使主干代码始终保持在可发布状态的主要保证。

    • 在单仓中,请确保测试的质量及覆盖率足够支撑持续集成。持续测试是持续集成的主体。如果没有足够的测试,持续集成能起到的作用非常有限。

    • 持续集成应该标准化。您不会希望看到单仓内的每个项目都有独立的几十条流水线,整个单仓有几万条流水线。这样无法达到持续集成所希望达成的质量保证。

    • 持续集成需要尽快得到结果。保持持续集成的畅通是主干开发的另一必要前置。

    我们的实践:

    • 我们要求测试质量和覆盖率必须达标。我们将测试的质量和覆盖率置入 EPC 指标。

    • 我们对流水线进行集中治理和标准化。

    代码评审

    代码评审在大仓+主干开发的模式下非常重要。因为大仓的代码的合作程度更高,依赖关系会更加复杂,在大仓内的坏提交可能会比原来在小仓内有数百倍计甚至更高的破坏性。在维护左移与加强协作的情况下,代码的维护者很可能不是代码变更的作者,而是代码变更的评审者。如果没有足够良好的代码评审文化和实践,如果代码评审形同虚设,就无法通过代码评审来保证代码变更质量,则您可能需要考虑先培养代码评审的文化。

    高频次的细致的代码评审对代码评审工具有更高的要求。

    1. 代码评审工具需要和工作流程以及其它工具,如在线 IDE、静态检查、持续集成和持续发布等等。

    2. 代码评审的记录是宝贵的工程资料和技术积累,需要永久保留并且需要便于审阅回顾。

    3. 代码评审的流程需要清晰简洁,代码评审页面应该直观、响应速度快且无 bug。否则,开发人员可能会在被评审要求反复改代码之时迁怒于代码评审工具。

    我们的实践:我们采取了严格的 Code Review 的政策:

    1. 创立了 PCG 工程技能认证体系(https://iwiki.woa.com/space/SkillsCertification), 引入了 Readability 机制。

    2. 我们投入了大量精力培养工程师的代码评审文化,并且提供了大量的 Code Review 的培训。

    3. Code Review 的质与量作为考核标准。

    结构管理

    大仓的结构管理需要慎重设计 。随着开发人员的增加和仓库规模的增长,需要考虑如何将维持大仓目录结构,使得各团队在合作的同时又不失结构。一个好的大仓的目录结构应该是易于在未知情况下定位项目所在目录的,并且比较稳定。

    我们推荐在设计结构目录时考虑以下问题:

    1. 考虑不同语言的代码命名规范、存放惯例以及定位原则。假如,C++路径与引入完全一致,而与此相反,Java 没有类似的强制规定,但是惯例以 com.tencent...为 package 前缀。它们应该被放在何处?

    2. API 的放置。

    3. 第二方、第三方依赖的放置。

    4. 是否提供每个项目的目录结构的设计准则。是否提供脚手架。

    从经验上来看,与其说设计结构目录是设计一个最好的,不如说是设计一个最不坏的。

    依赖管理

    正向依赖:需要认真治理所有的第三方依赖。在大仓里如果不进行第三方依赖的治理,大仓/主干开发的优势就会慢慢消散。第三方依赖主要有两个治理方向:

    • 依赖可信:指所有的第三方源应该是可靠的。当前,我们对外部依赖并没有明确的限制,内部仓库会从 Github 甚至其它低可信源不受限地添加依赖。由于缺乏足够的代码审查,且导入众多且难以追踪,当前我们缺乏工具和流程解决第三方依赖的安全问题,如对高危漏洞的修复以及对外部源投毒的防御等。另外,这导致我们无法审查外部代码引入的 LICENCE 是否合规。

    • 依赖发散:指一个第三方库可能有同时有多个版本,或者一个版本的多个拷贝,或者一个版本的不同生成产物,在生产环境中使用。依赖发散可能会导致依赖地狱:指通过版本号来进行包管理时,由于依赖关系过于复杂,导致能够满足所有包之间依赖关系的版本配置不存在。

    一个理想的单仓是自包含的,即,所有的外部依赖都以源码的形式被引入了单仓。单仓自身能够完成对所有项目的构建而不需要构建时下载外部代码/制品。与此同时,您可能需要思考第二方库在大仓中的位置。

    反向依赖:大仓往往难以被外部仓库源码依赖。如果大仓内的库需要被反向依赖,请确保您有应对策略。通常有两个方案:

    1. 允许外部仓库以轻量的方式依赖大仓,如制品依赖、或者按需依赖等;

    2. 将被依赖的代码同步到一个小仓中,以供外部依赖。

    推荐实践及工具

    以下并非硬性要求,但是我们仍然积极推荐您准备以下实践及工具。另外请注意,我们推荐您制定并维护严格的工程规范,例如命名、分支拉取、发布策略、比腾讯代码规范更详细的语言规范。

    静态检查

    静态检查 (static analysis),包括基于规则的代码扫描、基于抽象语法树的静态分析和基于编译插桩的分析工具。静态检查可以提升代码质量,并减少代码评审的工作量。

    静态检查的范围可以比现有代码扫描广泛得多,比如:

    • API deprecation and auto replacement

    • Dead code detection and auto removal

    • Error prone code suggestion

    我们追求的目标是:将尽可能多的CR 意见转化为静态检查。静态检查一般在请求 MR 时触发,若有可能,尽可能将静态检查左移,在开发/编译时触发。

    我们的实践:

    我们将在持续集成阶段执行标准化的静态检查,提高静态检查报告的强制力,并在代码评审阶段要求开发人员做出反应。同时,我们将提供 IDE 插件以实现静态检查左移。

    轻量的代码浏览/检索

    当我们拥有一个大型仓库,有一个良好的代码浏览器可以减少代码阅读的成本,可以更好地达到代码的复用和分享。我们希望拥有一个代码浏览器,并做到:

    • 轻量, 理想情况下零设置成本;

    • 完整, 能够看到整个大仓的代码以及历史版本的代码,以及 blame 信息;

    • 有用, 具有语义索引,能够看到所有的引用与被引用,以及实现跳转;

    • 可以检索。

    但是,现有的浏览代码的方案都不完美:

    • 工蜂尚缺少语法索引

    • IDE 等本地阅读工具需要下载并进行本地索引

    我们的实践:我们希望有一个带有语义索引的代码浏览器,类似于https://cs.opensource.google

    Web IDE

    Web IDE 与代码浏览器一起可以降低代码修改和提交的成本。对于一些小的修改,例如纠正 typo,轻量的工具可以极大地增加提交者进行修改的意愿。

    大迁移

    迁移总是困难的, 尤其是与开发者日常工作息息相关的大规模的仓库迁移。当您要制定将众多小仓迁移至单仓的计划,请确保您考虑过以下核心问题:

    1.您是否需要提供紧急回迁方案?

    提供回迁方案会极大地增加迁移复杂度。如果您的单仓规模较可控(如 < 500 开发),可以考虑通过一些其它手段增加迁移成功的成功率,而不提供回迁方案。

    2.您准备先将仓库迁移到单仓再完成治理(即“挑战”中所提到的必须实践),还是先治理再迁移单仓,抑或不进行治理?

    同时,请确保您考虑过以下风险:

    1. 项目代码所在目录会因迁移改变,从而可能导致代码需要改变。如,从@fiber://src/迁移到@depot://devtools/fiber,相对的 package 可能会发生变化。以下解决方案均非完美:

      a.直接平移代码:可能会导致代码不符合组织规范,或导致无法编译/运行时错误

      b.对代码进行自动化修改(如 copybara):可能导致无法编译/运行时错误

      c.代码所有人自行维护:相当于把风险委任给代码所有人,但是若要长期保持迁出与迁入仓的同步,需要大量的努力。

    2. 仓库间的依赖关系会极大增加复杂度。

      a.一个简单的例子:小仓 A 依赖小仓 B,两者均需要迁移,则您需要 :

      i.将小仓 A 迁移至大仓 A,仍然依赖小仓 B。归档小仓 A

      ii.将小仓 B 复制到大仓 B

      iii.将大仓 A 的依赖转移至大仓 B

      iiii.此时方可归档小仓 B

      换言之,被依赖的仓库需要后迁移。这意味着,如果是一次性迁移多个小仓,您需要整理所有的依赖关系图,拓扑 排序使入度为 0(即不被依赖)的仓库先迁移,以此逐阶段迁移。

      b.如果一个小仓被单仓外的仓库依赖,您需要长期保证这个小仓依然可以存在并被依赖

    3. 开发团队可能需要准备一个从分支开发到主干开发的全过程,并且确保主干开发有足够的测试和 CI。在 CI 尚未准备好且开发团队经验尚浅的情况下,风险会很高。

    4. 项目的流水线需要迁移。将小仓的流水线迁移到大仓,需要保证大仓上迁移过去的流水线可以工作。

    5. 其它工具也同流水线一样,可能需要适配。

    我们的实践:相对效率,我们的迁移方案更强调安全性。

    1. 提供紧急回迁方案

    2. 先将小仓迁移至大仓之后再进行标准化

    3. 预先建立大仓内的开发规范,强制所有迁入大仓的项目在标准化后符合开发规范

    结语

    十年磨一剑,霜刃未曾拭。感谢 PCG 两年多的效能改革为如今的单仓提供了可能。

    路漫漫其修远兮,大迁移已经启航,我们会前进。

    展开全文
  • 代码仓库规范

    千次阅读 2018-12-24 12:33:28
    代码仓库规范 目录 背景 目标 代码仓库规范 仓库创建 权限管理 仓库初始化 .gitignore README.md 分支管理 Tag管理 代码仓库列表 参考链接   背景 代码仓库不规范往往会带来各种问题,影响代码质量...

     代码仓库规范

    目录

    背景

    目标

    代码仓库规范

    仓库创建

    权限管理

    仓库初始化

    .gitignore

    README.md

    分支管理

    Tag管理

    代码仓库列表

    参考链接
     

    背景

    代码仓库不规范往往会带来各种问题,影响代码质量及开发效率,如:

    1. 项目开发阶段,混乱的分支可能引起多人合作开发过程中的代码冲突

    2. 项目运维阶段,新功能或bug修复导致线上故障难以回滚

    3. 项目代码缺乏review,代码质量存在隐患

    4. 项目组中添加新同学,代码上手开发时间成本较高

    针对以上问题,制定代码仓库规范,通过流程化方式降低问题出现的可能性。

    目标

    除解决背景中提到的问题外,代码仓库规范旨在达成以下目标:

    1. 业务可持续:避免项目迭代到后期线上、开发等分支错乱,确保系统代码长期可维护,业务变化可追溯

    2. 知识传承:项目新同学可根据代码重复流程,降低上手成本,促进知识不断积累、传递

    3. 远程仓库整洁:只提交项目开发/测试/运行相关的文件,IDE配置文件、编译文件等不可上传污染远程仓库

    代码仓库规范

    仓库创建

    项目主R负责申请创建项目代码仓库,代码仓库的创建应遵循以下原则:

    1. 按照不同的项目创建相应的代码仓库,避免不相关项目的代码放到一个库

    2. 避免按工程创建代码库,易导致代码仓库过多的问题。合理做法是按业务或按功能将同类工程放入一个代码仓库中

    权限管理

    合理的权限管理可以避免项目主分支合入未review代码,权限管理应遵循以下原则:

    1. 项目成员拥有非主分支Write权限,组内非项目成员拥有Read权限

    2. 项目主R保留主分支Write权限,同时按需为相应同学开放Write权限

    3. Leader保留Admin权限

    仓库初始化

    .gitignore

    原则上除了源代码、配置文件、单元测试代码、数据库初始化SQL,其他文件都应该加入到 .gitignore 以避免上传至远程仓库。

    通用 .gitignore 文件模板如下,各项目可根据需要补充:

    代码块

    Plain Text

    .idea/
    .DS_Store
    *.iml
    target/
    *.log
    *.class
    .settings/
    .project
    *.jar
    *.war
    *.nar
    *.ear
    *.zip
    *.tar.gz
    *.rar

    README.md

    README文件的目的是帮助代码仓库的浏览者快速了解项目相关信息,在README文件中需要包含以下信息:

    1. 简要说明此代码库解决的问题

    2. 项目结构简介,以模块粒度说明每个模块的作用、运行环境、线上链接等

    3. 项目文档外链,如需求文档、设计文档等

    4. 其他注意事项,如项目特殊依赖等

    5. 问题及需求反馈

    README示例:

    分支管理

    良好的分支管理可以提高项目主分支代码质量,较为完整的分支示例及对应分支说明如下:

    分支名称

    说明

    作用

    注意事项

    由何分支检出(checkout)

    向何分支合入(merge)

    何时删除

    master

    主分支/线上分支

    上线前该分支打Tag

    保留Write权限,由项目主R进行合入

    N/A

     

    N/A

    develop

    公共开发分支

    供feature-*分支检出、合入,作为项目开发过程中的核心分支

    保留Write权限,项目开发成员不可直接在该分支提交代码,需要以PR方式合入

    master

    release-*

    N/A

    feautre-*

    个人开发分支/新功能分支

    项目开发成员各自独立持有使用

    开发人员间不可混用,避免开发过程中发生冲突

    develop

    develop

    完成合入操作后删除

    release-*

    预上线分支

    feature-*分支汇总至develop分支后进行预上线测试使用

    除修复测试出的bug外不做其他修改及提交

    develop

    master

    develop

    完成合入操作后删除

    hotfix-*

    线上bug修复分支

    临时性紧急修复线上bug

     

    master

    master

    develop

    完成合入操作后删除

    由于组内项目在进行项目拆分后(预计国庆节后开始项目拆分)同一代码仓库只会由2~3人同时维护,采用上述分支模板会降低开发效率且不会取得太高的收益,因此引入分支权限,使用较为简洁的分支进行开发及管理,只保留master、feature-*分支,遵循以下原则:

    1. 仓库必须有一个主分支(master),主分支只有部分同学有Write权限

    2. 上线作业/工程必须采用主分支上的代码

    3. 开发新功能(feature)、修复bug、测试,统一使用feature-*分支(简洁分支管理不存在develop分支,feature-*分支从master分支检出)

    4. feature-*分支向主分支合入需要以PR形式进行,并配合Code review,完成后由具有Write权限的同学合并至主分支

    5. 定期删除已合并至主分支的feature-*分支,避免仓库分支过多难以管理

    Tag管理

    Tag可以理解成不可更新的特殊分支,也可以理解为某次commit指定的易于理解的别名,方便项目发布过程中的版本管理及线上问题回滚。Tag管理遵循以下原则:

    1. Tag需要在上线前创建,上线所用的Tag需要在主分支上创建

    2. 项目上线需要以Tag为基准(例外:离线托管平台上的Spark等作业需要指定分支发布),保证线上发布版本能够找到对应Tag

    3. Tag一般不做删除

    Tag示例:

     参考链接

     

     

    展开全文
  • 谁不想拥有自己的代码仓库

    万次阅读 多人点赞 2021-08-21 02:16:36
    有时公司需要搭建自己的代码仓库 这时候,自己搭建代码仓库的好处就体现出来了。下面我们就讲讲如何使用 Gogs 搭建自己的代码仓库。 下载二进制程序 https://gogs.io/docs/installation/install_from_binary.html ...

    自己搭建代码仓库的好处

    1. github 在国外,从国内正常访问的话,速度很慢。
    2. gitee、codechina 在国内,访问速度倒是很快,但是单个仓库大小、仓库总数量都受平台限制。
    3. 有时公司需要搭建自己的代码仓库

    这时候,自己搭建代码仓库的好处就体现出来了。下面我们就讲讲如何使用 Gogs 搭建自己的代码仓库。

    下载二进制程序

    https://gogs.io/docs/installation/install_from_binary.html

    根据自己的平台下载压缩包,我的环境是 Linux amd64
    请添加图片描述

    解压

    [root@Box tmp]# tar xvf gogs_0.12.3_linux_amd64.tar.gz -C /opt/
    

    运行

    [root@Box gogs]# ./gogs web
    2021/08/20 15:30:36 [ WARN] Custom config "/opt/gogs/custom/conf/app.ini" not found. Ignore this warning if you're running for the first time
    2021/08/20 15:30:36 [TRACE] Log mode: Console (Trace)
    2021/08/20 15:30:36 [ INFO] Gogs 0.12.3
    2021/08/20 15:30:36 [TRACE] Work directory: /opt/gogs
    2021/08/20 15:30:36 [TRACE] Custom path: /opt/gogs/custom
    2021/08/20 15:30:36 [TRACE] Custom config: /opt/gogs/custom/conf/app.ini
    2021/08/20 15:30:36 [TRACE] Log path: /opt/gogs/log
    2021/08/20 15:30:36 [TRACE] Build time: 2020-10-07 03:03:48 UTC
    2021/08/20 15:30:36 [TRACE] Build commit: f0e3cd90f8d7695960eeef2e4e54b2e717302f6c
    2021/08/20 15:30:36 [ INFO] Run mode: Development
    2021/08/20 15:30:36 [ INFO] Listen on http://0.0.0.0:3000
    

    从浏览器进行后续部署

    http://<server_ip>:3000/install

    可能出现的问题:浏览器无响应。

    解决办法:关闭服务器防火墙。

    ubuntu:iptables -Xiptables -Ziptables -F

    centos:systemctl stop firewalld.service,永久关闭 systemctl disable firewalld.service
    请添加图片描述
    为了部署简单,数据库选用 sqlite3,这样就不需要安装任何数据库了,甚至 sqlite3 命令都不需要安装。

    登录

    请添加图片描述

    创建仓库并上传项目

    请添加图片描述

    开机自启

    这里着重讲一下开机自启,我尝试了好几种方式都不行,如下

    1. 在 rc.local 中添加 /opt/gogs/gogs web > /dev/null 2>&1 &,结果不生效,这行命令应该是执行了(在其上面添加了一句测试命令,执行到了),只是没有真正把 gogs 启动起来。
    2. 在 /etc/init.d/ 中添加自启脚本,链接到 rc[2-5].d 目录下,依旧不生效。

    最后发现,其实,

    gogs 已经提供了相应开机启动服务脚本,不过需要根据自己的配置修改

    /opt/gogs/scripts/systemd/gogs.service

    [root@Box systemd]# cat gogs.service
    [Unit]
    Description=Gogs
    After=syslog.target
    After=network.target
    After=mariadb.service mysqld.service postgresql.service memcached.service redis.service
    
    [Service]
    # Modify these two values and uncomment them if you have
    # repos with lots of files and get an HTTP error 500 because
    # of that
    ###
    #LimitMEMLOCK=infinity
    #LimitNOFILE=65535
    Type=simple
    User=root
    Group=root
    WorkingDirectory=/opt/gogs
    ExecStart=/opt/gogs/gogs web
    Restart=always
    Environment=USER=root HOME=/opt
    
    # Some distributions may not support these hardening directives. If you cannot start the service due
    # to an unknown option, comment out the ones not supported by your version of systemd.
    ProtectSystem=full
    PrivateDevices=yes
    PrivateTmp=yes
    NoNewPrivileges=true
    
    [Install]
    WantedBy=multi-user.target
    

    拷贝到 /usr/lib/systemd/system,并使能服务,重启

    [root@Box systemd]# cp gogs.service /usr/lib/systemd/system
    [root@Box systemd]# systemctl enable gogs.service
    Created symlink /etc/systemd/system/multi-user.target.wants/gogs.service → /usr/lib/systemd/system/gogs.service.
    [root@Box systemd]# reboot
    

    查看 gogs 是否启动

    [root@Box ~]# ps -ef
    ...
    root         916       1  1 17:45 ?        00:00:00 /opt/gogs/gogs web
    ...
    

    看到 gogs 已经自启了,浏览器也可以正常访问。

    展示

    这是我三年前在云服务器上搭建的,一直稳定运行到现在
    在这里插入图片描述
    在这里插入图片描述
    希望你们也拥有自己的代码仓库。

    展开全文
  • 国内代码仓库-码云

    千次阅读 2020-08-06 17:55:15
    相信使用github的同学会经常碰到这样的情况,当我们从github上面下载稍微大一点的代码的...它提供了一种功能,就是可以将github账号中的代码clone到码云仓库里面去。然后再从gitee上下载就非常快。巅峰速度可以达到1-2M
  • 在github创建一个代码仓库

    千次阅读 2021-07-18 12:39:38
    1.准备工作 ... 注意事项:一些浏览器由于版本或不被github支持而导致无法访问,...1.2登录github,新建一个代码仓库。 Repository name是指名称 Description (optional)是指添加描述(可以不填) 默认选择public即可,选
  • 本地Git代码仓库的搭建及使用 总结 前言 1.什么是git? 开源的最先进的分布式版本控制系统,没有之一 用以高效、高速的处理从很小到非常大的项目版本管理。 2.什么是版本控制系统? 版本控制是一种记录一...
  • git提交代码至代码仓库详细步骤

    千次阅读 2022-01-13 14:46:06
    git提交代码至代码仓库
  • CentOS7搭建可视化Gitlab代码仓库

    千次阅读 2022-03-16 16:06:11
    扩展 #Gitlab配置文件 /etc/gitlab/gitlab.rb #Gitlab默认安装目录 /opt/gitlab #Gitlab目录数据目录 /var/opt/gitlab #Gitlab代码仓库数据 /var/opt/gitlab/git-data #重新加载配置 gitlab-ctl reconfigure #查看...
  • git代码仓库迁移的步骤 1、在本地电脑创建一个文件夹,cd进入文件夹后执行下面的git命令。这个命令会对原仓库克隆一份裸版本库。然后会在文件夹下生成一份克隆后的git文件 。 git clone --bare git@code.aliyun....
  • GitHub代码仓库管理介绍

    千次阅读 2018-10-16 19:47:59
    repository 仓库, 一个代码仓库就是一个工程 team 团队,组织里可以创建多个团队,团队里有很多成员 一个用户可以创建多个组织,组织下可以创建多个团队,一个团队可以管理多个项目 二、如何创建仓库 1、注册...
  • gitlab:查看代码仓库存放地址

    千次阅读 2021-08-17 09:57:15
    Gitlab默认的仓库存储路径在 /var/opt/gitlab/git-data目录下,仓库存储在子目录repositories里面,可以通过修改/etc/gitlab/gitlab.rb文件中git_data_dirs参数来自定义仓库存储路径。 保存git代码路径时用的是hash...
  • Gitee 码云 - 创建代码仓库

    千次阅读 2019-05-22 19:09:47
    Gitee 码云 - 创建代码仓库创建仓库分两种情况情况一:fork 仓库 + clone 到本地基本流程步骤演示情况二:创建新仓库基本流程步骤演示参考资料 其实官网的教程说的很明白了。不过自己在笔记一次有助于消化吸收。 ...
  • 阿里云 代码仓库个人信息配置

    千次阅读 2020-03-02 14:32:23
    文章目录阿里云代码仓库个人信息配置1. `首先,你需要有一个阿里云账号`2. 访问 `https://code.aliyun.com/`3. 点击 设置 —> 个人设置 完成个人代码信息的配置4. 点击 SSH 公钥,并配置个人电脑 GIT SSH 公钥 ...
  • github 代码仓库转移 方法一

    千次阅读 2019-12-28 16:27:17
    从原github地址clone一份代码。然后本地 1、找到.git目录 2、打开config文件 3、修改仓库地址 4、提交就可以了 git push --all origin
  • GitHub-紫书代码仓库
  • 如何在 GitLab 上创建代码仓库

    万次阅读 2019-07-20 11:26:58
    最近在做公司项目代码仓库迁移事情,经领导考虑再三最终还是选择了 Gitlab, 相关的原因大家可以看看这篇文章→ 走你 那么接下来介绍一下如何在 GitLab 上创建仓库以及一些注意点: 一.常规流程 → 登录、注册 ...
  • TortoiseSVN 创建 windows 本地代码仓库

    千次阅读 2020-03-24 18:34:00
    首先下载一个 TortoiseSVN ,我用的是一个野生网站随便下载...创建代码仓库 安装成功以后,随便找一个路径,创建一个 svnWare 文件夹(名字随意),比如我这里: 记录下这个路径,打开 cmd ,输入: svnadmin create...
  • coding代码仓库的配置和代码上传

    千次阅读 2018-04-27 14:56:16
     在本地创建一个文件夹,作为你上传代码的本地仓库,接下来就要把这个仓库与coding服务器端进行配置  在这个文件夹内点击右键,选择Git Bash Here,首先要初始化本地仓库,输入"git init"命令  接下来克隆远程...
  • Azure Repos 实际上就是 Repository,代码仓库,也就是类似于 Github,SVN,TFVC,Subversion 等等,对代码进行统一托管的服务。 在 Azure DevOps 中可以有两种托管方式,一种是 git,另一种是 TFVC,这个是在...
  • 如何使用Gradle脚本上传代码仓库 目录 上传本地代码仓库 上传JitPack 上传Jcenter 上传私有云Maven仓库 上传本地代码仓库 使用localRepositoryUpload.gradle可以将代码打包上传至本地代码仓库,方便...
  • 文章以 Springboot 官方的 HelloWorld 项目为例,教你掌握Springboot项目生产环境搭建、持续集成环境搭建。
  • github 删除代码仓库

    千次阅读 2016-05-06 09:11:05
    对于刚学习使用github的童鞋,肯定会创建一些没有用的代码仓库。于是,我就想删除刚开始创建的无用的代码仓库。 一.首先,登陆你的账号。会显示你的代码仓库。 二.点击你要删除的代码仓库,我删除test1,找到如图...
  • 这时候,本地仓库的配置就完成了,将要上传的代码文件放入这个文件夹中,接下来要查看一下本地仓库的状态,一检查配置是否成功,进而进行代码的推送,输入命令”git status” 例如放入了一个“stringKMP.c”文件...
  • gitlab外网代码仓库迁移至内网

    千次阅读 2018-10-26 14:44:30
    git clone --base 外网代码仓库地址 2、修改远程仓库地址 git remote set-url orign 内网仓库地址 3、push代码到远程仓库 git push --mirror 内网代码仓库地址 git常用命令 git remote --all git ...
  • 使用SourceTree来管理SVN的代码仓库,不能像Git仓库那样直接从URL来Clone,应该先通过指令在本地创建SVN- Git仓库,然后,将该仓库添加到SourceTree中进行管理; 创建本地仓库 首先,在本地创建一个空白文件夹,...
  • nexus代码仓库,Gitlab代码仓库构建

    千次阅读 2016-02-19 15:15:31
    我拿到手的是仓库的超级用户及仓库的外网访问地址。  和朋友开玩笑说:只要有以下这一步,其实啥都可以解决。  可在具体的使用中时,依旧磕磕绊绊。我想,还是自己做一些笔记,那样回来的更稳当。而学习,一直是一...
  • github建立自己的代码仓库

    千次阅读 2020-06-22 13:34:22
    参考
  • gradle仓库 首先,Repository 是什么?Repository 是 文件的集合,这些文件,通过group、name和version 组织起来。在使用上,主要体现为jar 和 xml文件。 Gradle 通过这些Repository 找到外部依赖(external ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 462,950
精华内容 185,180
关键字:

代码仓库