第一次听到同事说"你把那份 repo 拉下来"的时候,我脑子里闪过的第一反应是某个软件的下载源——毕竟在 Linux 环境里混久了,repo 这个词十有八九出现在 /etc/yum.repos.d 目录下面。结果他打开终端敲的是 repo init,我才发现自己和他说的是两件完全不相干的事。这个小误会其实挺有代表性:在 Linux 生态里,repo 既是那套用来统一管理上百个 git 仓库的 Python 脚本,也是 yum/dnf 眼里的软件源配置文件后缀。两者只有名字撞车,从下载方式、使用方法到排错思路全都不一样。所以这篇就按这两条线分开讲,把 repo 工具的下载安装、manifest 清单写法、sync 参数取舍,以及 .repo 文件的配置和那个经典的 "cannot find a valid baseurl for repo" 报错排查,一次讲透。
1. 先分清两个"repo":多仓库管理工具与软件源配置文件
很多人第一次被 repo 绕晕,不是因为技术难,而是因为搜索"repo 下载"的时候,搜索结果一半是讲 Android 源码拉取的,另一半是讲 CentOS 换源的,两边说的都对,但混在一起看就完全对不上号。搞清楚自己站在哪条线上,后面所有操作才有意义。
1.1 repo 脚本的本质:一个包装了 git 的 Python 调度器
Google 那套 repo 并不是包管理器,它一行命令都装不了软件。它的真实身份是一个 Python 脚本,核心作用是把"同时操作几十上百个 git 仓库"这件事变成一条命令能搞定。你执行 repo sync 的时候,它在背后做的事情是:读取 manifest 清单,逐个进入对应目录,执行 git fetch 和 git checkout,然后汇总结果。
理解这一点之后,很多行为就顺理成章了。为什么 repo 的报错里全是 git 的味道?因为它就是在调 git。为什么 repo 的工作目录下会多出一个.repo隐藏目录?因为清单仓库、脚本自身、每个项目的 git 元数据都塞在里面。为什么切分支要用 repo start 而不是 git checkout?因为单个项目的分支切换在几十个仓库里没法批量做,repo 帮你循环了一遍。
还有个容易忽略的点:repo 脚本本身也放在.repo/repo目录里,repo init时会自动拉一份下来。这就埋下了一个坑——很多人喜欢给 repo 打"中文补丁"汉化提示信息,结果下次 init 或者脚本自更新时,.repo/repo被整体覆盖,改动全丢。如果你确实需要汉化,要么在每次更新后重新应用,要么干脆别动脚本本身,靠alias包一层自己的提示逻辑。
1.2 .repo 文件与 yum/dnf:包管理器眼里的仓库地址
另一条线的 repo 就朴素多了。它就是一个纯文本配置文件,放在/etc/yum.repos.d/下面,写完保存即生效。一个典型的文件长这样:
[base] name=CentOS-$releasever - Base baseurl=https://mirrors.aliyun.com/centos-vault/7.9.2009/os/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 enabled=1方括号里的[base]是仓库 ID,baseurl是真实地址,$releasever和$basearch是变量。这里最需要建立的认知是:baseurl 里的变量不是 shell 展开的,是 yum/dnf 自己展开的。所以你在终端里echo $releasever得到空白,一点都不奇怪,那是 shell 变量,跟仓库配置无关。想看真实值,得用yum -v repolist或者dnf repolist -v,它会打印每个仓库展开后的完整地址,这是排查所有 baseurl 问题的第一步。
1.3 看到报错怎么一秒定性
两条线各有各的专属报错,混不了。下面这张表我在团队内部文档里放了好几年,新同事看到报错先对一遍,基本能立刻判断方向。
| 报错片段 | 属于哪条线 | 第一反应该做什么 |
|---|---|---|
| cannot find a valid baseurl for repo: base/7/x86_64 | yum/dnf 软件源 | 检查 baseurl 拼写、镜像站路径是否存在、DNS 是否通 |
| error.GitError: manifests ... | repo 工具 | 检查 manifest 仓库地址、分支名、凭据是否配置 |
| repo: command not found | repo 工具 | PATH 里没有 repo 脚本,检查 ~/bin 是否加入 PATH |
| Failed to download metadata for repo | yum/dnf 软件源 | 先用 curl 直接测 baseurl 能否下载 repodata |
| fatal: unable to access ... Could not resolve host | 两条线都可能 | 网络或 DNS 问题,不是配置写错 |
这张表最有用的一行是最后一行。很多新手看到 "Could not resolve host" 还去翻 repo 文件,其实那是域名解析的问题,你在/etc/yum.repos.d/里改到天亮也没用。先分清是"配置错"还是"路不通",方向就对了。
2. repo 工具的获取与首次初始化:从下载到 sync 成功
这条线是真正需要"下载"的——你总得先把那个 Python 脚本拿到手。但拿脚本这件事本身也有讲究,渠道选错、权限不对、依赖缺失,都会让你在第一步就卡住。
2.1 下载渠道的三种选择与各自的坑
主流做法有三种,我按推荐顺序排:
第一种是通过发行版包管理器直接装,比如apt install repo或者yum install git-repo。好处是依赖自动处理、版本跟着发行版走;坏处是版本可能偏老,遇到新仓库的 manifest 报错时不好定位。
第二种是手动下载官方 launcher,放到~/bin/repo然后chmod a+x。这是最通用的方式,任何发行版都能用。命令大致是:
mkdir -p ~/bin curl -o ~/bin/repo https://storage.googleapis.com/git-repo-downloads/repo chmod a+x ~/bin/repo export PATH="$HOME/bin:$PATH"注意-o是大写字母 O,这是覆盖输出文件的意思。小写-o是把日志写到指定文件,很多人手抖写成小写,结果发现目标文件里全是连接日志,仓库文件一个字都没有。用 wget 同理,wget -O才是写文件。这个大小写细节在配置 yum 源的时候同样会咬人,后面第 4 节还会再提一次。
第三种是从国内镜像站拿,很多高校和企业镜像都提供了 git-repo 的包或脚本副本。这种方式下载体验通常更好,但要注意版本对齐——镜像可能滞后,最好记录下你用的具体版本,方便复现问题。
不管走哪条路,装完先跑repo --version确认脚本可执行、Python 解释器能找到。如果提示env: python: No such file or directory,说明脚本头部指向的解释器不存在,早期版本的 repo 写死了#!/usr/bin/env python,而你的系统只有python3,这种情况下要么装个兼容包,要么用新版本的 launcher。
2.2 环境依赖:三个容易漏掉的前置条件
repo 官方文档里那几行依赖说明很容易被跳过,但漏一个就得出问题。
Python 版本。现在的 repo 需要 Python 3.6 以上。老系统上默认 python 还是 2.7 的话,repo init会直接抛语法错误。先python3 --version确认,必要时在脚本里改成显式调用 python3。
git 版本与基础配置。git 建议 1.8 以上,太老的话--partial-clone、--filter这些参数用不了。另外git config --global user.name和user.email必须提前配好,否则repo sync到一半需要创建提交时会失败,或者repo upload直接拒绝。这个错误信息出现得很晚,等你同步了几个 G 才蹦出来,非常打击人。
PATH 与目录权限。脚本放到~/bin之后,确认这个目录在 PATH 里;同时确保工作目录有足够权限和空间。sync 动辄几十 G,放在空间紧张的根分区是自找麻烦。
2.3 repo init 参数逐个拆解
初始化是整个流程里参数最多的一步,我把常用的挑出来讲,重点是"为什么这么选"。
repo init -u https://example.com/manifests.git \ -b main \ -m default.xml \ --depth=1 \ --no-clone-bundle \ --git-lfs-u指向 manifest 仓库地址,这是唯一的必填项,它决定了你后面能同步到哪些项目。-b指定分支,不写就是默认分支,实际项目里一定要写清楚,否则别人复现不了你的环境。-m指定用哪个清单文件,一个 manifest 仓库里往往有多个 xml,比如针对不同硬件平台的配置,-m就是选择开关。
--depth=1是浅克隆,只拉最近一次提交。这个参数能显著减少下载量和磁盘占用,但代价是git log只能看到一条记录、git blame基本废掉。如果你需要查历史或者做代码考古,别开它;如果只是编译验证、跑测试,开了能省很多时间。
--no-clone-bundle跳过打包下载。repo 在某些情况下会优先尝试下载一个打包好的 bundle 文件,速度更快,但如果服务器上那个 bundle 不存在或者过期,反而会多一轮失败重试。网络环境不理想的时候,直接加这个参数跳过,老老实实走 git 协议,行为更好预期。
--git-lfs是给用大文件存储的仓库准备的。如果你的项目里有二进制资源,不加这个参数,同步下来的是几十字节的指针文件,编译时才报错说资源缺失,排查起来很绕。
还有一个--no-repo-verify,跳过对 repo 脚本自身签名的校验。默认情况下 repo 会校验自己的 GPG 签名,如果环境里没有对应的公钥或者校验链路走不通,就会卡住。这个参数只在你清楚自己在干什么的时候用,日常不建议随手加。
2.4 首次 sync 的耗时预估与断点续传
初始化只是写好了清单,真正下代码是repo sync。我的习惯是:
repo sync -c -j8 --no-tags --fail-fast-c只同步当前分支,省掉一堆用不上的远端分支。-j8是并发数,一般取 CPU 核数的 1 到 2 倍,并发太高反而会因为磁盘 IO 和网络连接数限制变慢,我在机械硬盘的机器上试过-j16,比-j4还慢。--no-tags不拉标签,能省一点。--fail-fast遇到第一个错误就停,方便你立刻处理,不然它会把几十个仓库的错误信息全刷一遍,真正有用的那行被淹掉。
中断了怎么办?直接重跑同一条命令就行,repo 会跳过已经同步好的项目,从断的地方接着来。这是它比手写 for 循环方便的地方之一。如果某个项目状态混乱,加--force-sync强制重新拉取;实在不行删掉那个项目的目录重新 sync,别去.repo里手动改元数据,改坏一次要花半天恢复。
3. manifest 才是 repo 的大脑:xml 清单文件怎么读怎么写
sync 能跑起来不代表你理解了 repo。真正决定"同步哪些仓库、放在哪个目录、用什么版本"的,是 manifest 这个 xml 文件。看懂它,你才能改它。
3.1 manifest 的基本骨架
一个最简的清单大概是这样:
<manifest> <remote name="origin" fetch=".." /> <default remote="origin" revision="main" sync-j="4" /> <project name="platform/framework.git" path="framework" /> <project name="platform/apps.git" path="apps" revision="dev" /> <linkfile src="README.md" dest="README-link.md" /> <copyfile src="tools/build.sh" dest="build.sh" /> </manifest>remote定义了仓库的基地址,fetch=".."是相对路径写法,配合name字段拼出完整 URL。default给所有项目设定默认的远端和分支,sync-j还能在清单层面定并发数。project是主体,name是仓库名,path是同步到本地的哪个目录——这两个不一定是同名,很多项目会刻意把path简化成短目录名,方便敲命令。
linkfile和copyfile是两个很有意思的指令,容易被人忽略。它们的作用是"同步完成后顺手做个软链接或复制"。软链接适合共享文档、配置文件;复制适合构建脚本这类需要独立副本的场景。团队里统一构建入口的时候,用copyfile把公共脚本铺到每个项目根目录,比让每个人自己复制可靠得多。
3.2 多清单与 include:把配置拆成几层
真实项目很少只有一个 xml。常见做法是分层次:
<manifest> <include name="base.xml" /> <include name="hardware/board-a.xml" /> <project name="vendor/extra.git" path="vendor/extra" /> </manifest>include让上层清单引用下层清单,实现"公共部分 + 增量部分"的组合。这样维护起来清楚:基础配置改一次,所有引用它的产品线都跟着变;产品特有的仓库单独放一个文件,不会污染主干。
需要注意 include 的路径是相对于 manifest 仓库根目录的,写相对路径的时候别加前导斜杠。另外被 include 的文件合并顺序会影响覆盖关系,同一个 project 在两处定义时以哪个为准,跟文件里的先后位置有关。改清单之前,先repo manifest看一眼合并后的最终结果,比盯着源文件猜要靠谱。
3.3 local_manifests:本地改动不被冲掉的正确姿势
"我改的清单怎么一 sync 就没了"——这是使用 repo 最常听到的抱怨。原因是有人直接改了 manifest 仓库里的文件,而 sync 会把它 reset 回去。正确做法是把本地定制放在.repo/local_manifests/目录下:
mkdir -p .repo/local_manifests cat > .repo/local_manifests/my.xml <<'EOF' <manifest> <remove-project name="platform/apps.git" /> <project name="myfork/apps.git" path="apps" revision="hotfix" /> </manifest> EOF这份文件会在主清单之后合并,remove-project先把原项目摘掉,再用自己的 fork 补上。改完必须再跑一次repo sync才生效,因为合并是在 sync 时进行的,不是实时读取的。这个细节坑过不少人:改完 local_manifests 立刻repo status,发现还是老仓库,以为配置没被识别。
3.4 高频命令速查与使用场景
| 命令 | 作用 | 我的使用场景 |
|---|---|---|
| repo start myfix --all | 给所有仓库建同名分支 | 开始一个跨模块的改动 |
| repo status | 汇总各仓库的改动状态 | 提交前扫一遍,确认没漏文件 |
| repo diff | 显示各仓库的 diff | 快速过一遍改动内容 |
| repo forall -c 'git log -1' | 在所有仓库执行同一命令 | 核对每个仓库停在哪个提交 |
| repo prune | 清理已合并的本地分支 | 每季度做一次,回收空间 |
| repo manifest -r -o pinned.xml | 导出锁定版本的清单 | 发布节点存档,复现构建环境 |
| repo grep "关键词" | 跨仓库搜索 | 找某个接口在哪些仓库被调用 |
其中repo manifest -r我认为是被低估最多的一个命令。它会把所有项目的当前 commit id 固化成一份新清单,发布版本、交接、复现线上问题的时候,这份文件的价值极高——只要有它和仓库访问权限,别人就能还原出和你一模一样的环境。我自己维护的项目,每次发版都会导出一份,按日期命名归档。
4. yum/dnf 源配置:从 "cannot find a valid baseurl for repo" 说起
换到软件源这条线,最经典的报错就是那一长串cannot find a valid baseurl for repo: base/7/x86_64。它看起来像是一个错误,实际上是一类错误的统称,背后至少藏着四层原因。
4.1 报错背后的四层原因
第一层:仓库地址已经不存在了。CentOS 7 停止维护之后,原来的mirror.centos.org/centos/7/路径下线,内容被归档到 vault 目录。老机器上那套默认源配置文件指向的地址还在,但内容没了,于是 404,yum 报 baseurl 无效。这是这两年最高频的原因。
第二层:变量取到了意外值。报错里那个7就是$releasever展开的结果。在 CentOS Stream 上,$releasever可能是8-stream,如果 baseurl 里写的是硬编码的7,两者对不上,路径自然找不到。反过来,在 7 上用了8的源,同样报错。
第三层:域名根本解析不了。DNS 配置有问题时,yum 拿到的结果和"地址不存在"是一样的表现,都会走到 baseurl 无效这条分支。所以排查的第一步应该是curl -I直接测一下 baseurl 里的地址能不能通,而不是先改配置文件。
第四层:baseurl 和 mirrorlist 都没写。有些配置文件里两个字段都被注释掉了,或者写错了字段名(比如写成base_url),yum 找不到任何可用地址。这类问题看一眼文件就能发现,但如果是复制粘贴来的配置,很容易带着注释符号一起贴进去。
4.2 手写一份可用的源配置
我通常用镜像站提供的现成配置文件覆盖,最省事:
cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo这里再次强调-O大写。热词里有个流传很广的写法用的是小写-o,照着敲的结果是:wget 把下载日志写进了centos-base.repo,真正的仓库文件落在当前目录。你打开那个文件看到一堆连接信息,还以为是镜像站返回的内容有问题,能排查到怀疑人生。
如果镜像站提供的现成文件版本对不上,就手写。CentOS 7 归档场景下的推荐写法:
[base] name=CentOS-7 - Base - vault baseurl=https://mirrors.aliyun.com/centos-vault/7.9.2009/os/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 enabled=1关键是把路径从centos/换成centos-vault/,并且补上具体的小版本号。小版本号可以去镜像站的目录列表里现查,不要凭记忆填。
4.3 cleancache 的顺序为什么不能反
改完源配置,接下来这两条命令的顺序是有讲究的:
yum clean all yum makecacheclean all清掉的是本地缓存的仓库元数据(repodata),makecache是根据新配置重新下载并缓存。如果顺序反了,或者只做 makecache 不做 clean,本地的旧元数据还在,yum 会认为自己有可用的缓存,直接跳过下载,于是你看到的还是旧仓库的信息,甚至继续报 baseurl 错误。这也是"我明明改对了配置怎么还报错"最常见的解释。
dnf 系统上把 yum 换成 dnf 即可,参数一致。另外yum clean all之后第一次yum install会慢一些,因为要重建缓存,这是正常的,别以为卡住了就 Ctrl+C 打断。
4.4 验证变量展开的三种手段
改完之后怎么确认生效?我一般用三种方式交叉验证:
第一种是yum -v repolist,它会打印每个仓库展开后的 baseurl,直接看地址对不对。dnf 用dnf repolist -v。
第二种是手工验证解析路径,比如查一下系统实际的版本信息:
grep -E '^(VERSION_ID|PLATFORM_ID)' /etc/os-release rpm -q --qf '%{VERSION}\n' centos-release第三种是在/etc/yum.conf的[main]段里临时指定releasever,比如releasever=7,用来绕过系统版本识别异常的情况。这属于应急手段,长期用会让配置和系统脱节,问题排查完记得撤掉。
5. 踩坑实录:几条真实的排查链路
前面讲的都是结构化的知识,但实际操作中让人头大的往往是那种"配置看起来都对,就是不通"的情况。下面几条是我印象最深的排查过程,思路可以照着复现。
5.1 repo sync 卡住不动与浅克隆的代价
有次同步一个大型项目,repo sync跑到 60% 之后长时间没有输出,终端一片安静。第一反应是网络断了,但ping目标域名是通的。加了-v重跑,发现卡在某个仓库的Fetching projects上,那个仓库历史特别大。
当时的处理是分两步:先 Ctrl+C 中断,然后针对性处理那个仓库。单独进它的目录执行git fetch --depth=1 origin 分支名,用浅克隆把体积压下来,再回到根目录重跑repo sync。后续再同步时,我在 init 阶段就加上了--depth=1,并且在清单里给体积大的项目单独标了clone-depth="1"。
这里的经验是:浅克隆不是万能的,它是一个权衡。省了空间和时间,代价是历史不可查、某些依赖历史提交的构建脚本会失败。判断标准很简单——你是要编译验证,还是要读代码。前者开,后者关。
顺带说一个相关的小坑:repo sync中断后重复执行,绝大多数情况能续传,但如果中断发生在 manifest 仓库的更新过程中,可能留下半个状态,表现为repo init报清单解析错误。这时候把.repo/manifests目录删掉重新 init,比在原地反复 sync 快得多。
5.2 源配置没问题却仍报 baseurl:DNS 的干扰
一个同事的机器换了网络环境之后,yum 全挂,报的还是那个 baseurl 无效。我们对照配置文件看了三遍,路径、变量、gpgkey 全对。用curl -I测 baseurl,报域名解析失败。
问题出在 DNS。动态获取地址的时候,/etc/resolv.conf被网络管理服务反复重写,里面指向的解析地址不可用。临时处理是手动加一行可用的解析地址,但重启后会被覆盖。长期方案是在网络配置里静态指定,或者调整解析服务的监听方式(有些系统上本地解析服务会监听回环地址的特定端口,直接看/etc/resolv.conf里的nameserver就能确认)。
这个案例的关键判断点在于报错位置和真实原因不一致。yum 把"域名解析不了"和"地址不存在"归到了同一类报错里,你不主动去测网络,就会一直在配置文件里打转。
顺便提一句另一个容易混淆的报错:如果日志里出现的是GPG key retrieval failed,那说明 baseurl 是通的、仓库连上了,问题出在 gpgkey 地址不可达或者本机没有对应公钥。这时候该查的是gpgkey那一行,而不是 baseurl。分不清这两个报错,排查方向会完全跑偏。
5.3 中文文件名与 quotepath 的显示问题
这条和前面的主题不同,但实际工作中撞上的概率很高。同步下来的项目里有中文文件名,git status显示成一串反斜杠加数字,比如"\346\226\207\346\241\243.txt"。这不是文件损坏,是 git 默认对非 ASCII 文件名做了转义。
处理办法是关掉它:
git config --global core.quotepath false改完之后再执行git status,中文名就正常显示了。这个配置对所有仓库生效,属于我装机必做的一步。
如果是解压压缩包出现乱码,那是另一个问题。老式 zip 包在 Windows 下打包时用的是 GBK 编码,Linux 默认按 UTF-8 解读,于是文件名全乱。解压时可以指定编码:
unzip -O GBK 压缩包.zip -d 目标目录系统自带的 unzip 不一定支持-O参数,不支持的话换用unar之类的工具,它会自动探测编码,省心不少。
5.4 磁盘被 .repo 吃掉之后怎么回收
用久了会发现.repo目录越来越大,du -sh .repo一看比工作目录还夸张。原因有三块:每个项目的 git 元数据、所有远端分支的引用、以及不再需要的打包文件。
能做的清理有限但有帮助。repo prune会删掉已经合并到当前分支的本地分支,这是安全的。repo forall -c 'git gc --prune=now'可以对各仓库做一次垃圾回收,但很耗时间,建议在空闲时跑。
需要提醒的是,不要手动去.repo/projects下面删目录,那会和.repo/project.list的记录对不上,导致后续 sync 行为异常。真要清理,宁可整个项目删掉重新 init + sync,虽然费时间,但状态是干净的。
6. repo 与 git 的分工:什么时候该用 repo,什么时候纯 git 就够
讲了这么多操作,最后回到一个选型问题:一个项目到底该不该上 repo?我见过不少团队为了"看起来规范"引入 repo,结果多了一层复杂度却没人用上它的核心能力。
6.1 manifest 锁版本才是 repo 的核心价值
repo 最不可替代的能力,是把"几十个仓库都停在某一组确定的提交上"这件事变成一个可存储、可传递、可复现的文件。这在多模块、多团队协作的项目里价值极高——发布一个版本,导出一份锁定清单,任何人拿到它都能还原出完全一致的代码树。
如果你的项目只有一个仓库,或者几个仓库之间没有严格的版本对应关系,那 repo 带来的收益很小,纯 git 就够了。判断标准可以简化成一句话:你需不需要"一批仓库的整体快照"?需要,就上 repo;不需要,别给自己加负担。
6.2 submodule 与 repo 的对照
git 原生也有 submodule 来解决多仓库问题,两者经常被拿来比较。我自己两个都用过,感受如下。
| 维度 | repo | git submodule |
|---|---|---|
| 配置载体 | 独立的 manifest 仓库 | 主仓库里的 .gitmodules |
| 批量操作 | 原生支持,forall 一条命令 | 需要自己写循环脚本 |
| 版本锁定 | manifest 导出即快照 | 靠子模块的 commit 指针 |
| 学习成本 | 多一套命令和概念 | 概念少但细节多,容易踩坑 |
| 适合场景 | 仓库数量多、需要统一快照 | 少量第三方依赖、轻量引用 |
submodule 的痛点是操作繁琐,更新子模块、切换分支、递归拉取都容易出错;repo 的痛点是多了一套工具链和 manifest 维护成本。仓库数量在十个以内、依赖关系简单的话,submodule 更轻;上了几十个仓库,repo 的优势就明显了。
6.3 团队协作中的几个习惯
最后分享几个我在带团队时推行过的习惯,都是踩坑换来的。
分支命名统一加前缀。repo start fix-xxx --all会在所有仓库建同名分支,如果每个人的命名风格都不一样,repo branches的输出会非常乱,出问题时很难判断是哪个任务引入的改动。统一成fix-、feature-这类前缀,一眼能看出性质。
提交前先跑 repo status。跨仓库改动的常见事故是漏提交——在 A 仓库改了实现,忘了在 B 仓库提交对应的接口变更,本地跑得通,别人同步下来就编译失败。repo status扫一遍,确认每个有改动的仓库都在计划内。
导出锁定清单作为发布产物。前面提过,这里再强调一次:发版时repo manifest -r -o导出的那份 xml,应该和编译产物一起归档,而不是只放在某个人电脑上。半年后有人要复现问题,这份文件能省下几天时间。
不要在源配置和 repo 工具之间来回切换思路。这是本文开头那个误会的延伸——遇到报错先看关键词,属于哪条线就用哪条线的排查路径,别把 yum 的问题当成 manifest 的问题来查,那是最容易浪费时间的做法。
最后补一句关于中文补丁的个人看法:我知道很多人喜欢把 repo 的提示信息汉化,看起来亲切。但脚本会在 init 或自更新时被覆盖,而这个覆盖往往发生在你最不想出问题的时刻。与其维护一份会被冲掉的改动,不如花点时间熟悉那几十条英文提示——它们其实就那么几句话反复出现,认熟了比查汉化补丁快。