提交者指南

商标

FreeBSD 是 FreeBSD 基金会的注册商标。

Coverity 是注册商标;Coverity Extend、Coverity Prevent 和 Coverity Prevent SQS 是 Coverity, Inc. 的商标。

IBM、AIX、OS/2、PowerPC、PS/2、S/390 和 ThinkPad 是 International Business Machines Corporation 在美国、其他国家/地区或两者的商标。

Git 和 Git 徽标是 Software Freedom Conservancy, Inc.(Git 项目的企业主体)在美国和/或其他国家/地区的注册商标或商标。

GitHub 是 GitHub Inc. 的商标,在美国和其他国家/地区注册。

GITLAB 是 GitLab Inc. 在美国和其他国家/地区和地区的商标。

Intel、Celeron、Centrino、Core、EtherExpress、i386、i486、Itanium、Pentium 和 Xeon 是 Intel Corporation 或其子公司在美国和其他国家/地区的商标或注册商标。

制造商和销售商用来区分其产品的许多名称都被认定为商标。如果这些名称出现在本文档中,并且 FreeBSD 项目了解商标声明,则这些名称后面将加上“™”或“®”符号。

摘要

本文档提供有关 FreeBSD 提交者社区的信息。所有新提交者在开始之前都应阅读本文档,并且强烈建议现有提交者不时地复习它。

几乎所有 FreeBSD 开发人员都对一个或多个存储库拥有提交权限。但是,一些开发人员没有提交权限,这里的一些信息也适用于他们。(例如,有些人只有权限处理问题报告数据库。) 请参阅 非提交者开发人员特有的问题 以获取更多信息。

本文档也可能让想要了解项目工作原理的 FreeBSD 社区成员感兴趣。


1. 管理细节

登录方法

ssh(1),仅协议 2

主 Shell 主机

freefall.FreeBSD.org

参考机器

ref*.FreeBSD.org, universe*.freeBSD.org (另请参见 FreeBSD 项目主机)

SMTP 主机

smtp.FreeBSD.org:587 (另请参见 SMTP 访问设置).

src/ Git 存储库

ssh://git@gitrepo.FreeBSD.org/src.git

doc/ Git 存储库

ssh://git@gitrepo.FreeBSD.org/doc.git

ports/ Git 存储库

ssh://git@gitrepo.FreeBSD.org/ports.git

内部邮件列表

developers (技术上称为 all-developers)、doc-developers、doc-committers、ports-developers、ports-committers、src-developers、src-committers。(每个项目存储库都有自己的 -developers 和 -committers 邮件列表。这些列表的存档可以在 freefall.FreeBSD.org 上的 /local/mail/repository-name-developers-archive/local/mail/repository-name-committers-archive 文件中找到。)

核心团队月度报告

/home/core/public/reportsFreeBSD.org 集群上。

移植管理团队月度报告

/home/portmgr/public/monthly-reportsFreeBSD.org 集群上。

值得注意的 src/ Git 分支

stable/n (n-STABLE)、main (-CURRENT)

ssh(1) 必须连接到项目主机。有关更多信息,请参见 SSH 快速入门指南.

有用链接

2. FreeBSD 的 OpenPGP 密钥

FreeBSD 项目使用符合 OpenPGP (Pretty Good Privacy) 标准的加密密钥来验证提交者。带有重要信息的邮件(如公共 SSH 密钥)可以使用 OpenPGP 密钥签名以证明它们确实来自提交者。有关更多信息,请参见 PGP & GPG: 务实的偏执狂的电子邮件,作者迈克尔·卢卡斯https://en.wikipedia.org/wiki/Pretty_Good_Privacy

2.1. 创建密钥

可以使用现有的密钥,但应首先使用 documentation/tools/checkkey.sh 进行检查。在这种情况下,请确保密钥具有 FreeBSD 用户 ID。

对于那些还没有 OpenPGP 密钥或需要新密钥来满足 FreeBSD 安全要求的人,这里展示了如何生成密钥。

  1. 安装 security/gnupg。在 ~/.gnupg/gpg.conf 中输入以下几行以设置签名和新密钥首选项的最低可接受默认值(有关更多详细信息,请参见 GnuPG 选项文档

    # Sorted list of preferred algorithms for signing (strongest to weakest).
    personal-digest-preferences SHA512 SHA384 SHA256 SHA224
    # Default preferences for new keys
    default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 CAMELLIA256 AES192 CAMELLIA192 AES CAMELLIA128 CAST5 BZIP2 ZLIB ZIP Uncompressed
  2. 生成密钥

    % gpg --full-gen-key
    gpg (GnuPG) 2.1.8; Copyright (C) 2015 Free Software Foundation, Inc.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    
    Warning: using insecure memory!
    Please select what kind of key you want:
       (1) RSA and RSA (default)
       (2) DSA and Elgamal
       (3) DSA (sign only)
       (4) RSA (sign only)
    Your selection? 1
    RSA keys may be between 1024 and 4096 bits long.
    What keysize do you want? (2048) 2048 (1)
    Requested keysize is 2048 bits
    Please specify how long the key should be valid.
    	 0 = key does not expire
          <n>  = key expires in n days
          <n>w = key expires in n weeks
          <n>m = key expires in n months
          <n>y = key expires in n years
    Key is valid for? (0) 3y (2)
    Key expires at Wed Nov  4 17:20:20 2015 MST
    Is this correct? (y/N) y
    GnuPG needs to construct a user ID to identify your key.
    
    Real name: Chucky Daemon (3)
    Email address: notreal@example.com
    Comment:
    You selected this USER-ID:
    "Chucky Daemon <notreal@example.com>"
    
    Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
    You need a Passphrase to protect your secret key.
1目前 (2022-10),2048 位密钥和三年有效期提供了足够的保护。
2三年的密钥生命周期足够短,可以使被不断增长的计算机能力削弱的密钥过时,但又足够长,可以减少密钥管理问题。
3在这里使用您的真实姓名,最好与政府颁发的身份证上的姓名一致,以便其他人更容易验证您的身份。可以在“注释”部分输入有助于其他人识别您的文本。

输入电子邮件地址后,将请求您输入密码。创建安全密码的方法存在争议。这里没有建议单一方法,而是提供了一些链接到描述各种方法的网站:https://world.std.com/~reinhold/diceware.htmlhttps://www.iusmentis.com/security/passphrasefaq/https://xkcd.com/936/https://en.wikipedia.org/wiki/Passphrase.

保护私钥和密码。如果私钥或密码可能已被泄露或公开,请立即通知 accounts@FreeBSD.org 并吊销密钥。

提交新密钥的步骤在交叉引用:committers-guide[commit-steps,新提交者的步骤] 中显示。

3. FreeBSD 集群的 Kerberos 和 LDAP 网页密码

FreeBSD 集群需要 Kerberos 密码才能访问某些服务。Kerberos 密码也用作 LDAP 网页密码,因为 LDAP 在集群中代理到 Kerberos。一些需要此密码的服务包括

要使用随机密码生成器在 FreeBSD 集群中创建新的 Kerberos 帐户或重置现有帐户的 Kerberos 密码

% ssh kpasswd.freebsd.org

这必须在 FreeBSD.org 集群外部的机器上完成。

也可以通过登录 freefall.FreeBSD.org 并运行以下命令来手动设置 Kerberos 密码

% kpasswd

除非之前使用过 FreeBSD.org 集群的 Kerberos 身份验证服务,否则将显示 Client unknown。此错误意味着必须首先使用上面显示的 ssh kpasswd.freebsd.org 方法来初始化 Kerberos 帐户。

4. 提交位类型

FreeBSD 存储库具有多个组件,这些组件组合在一起支持基本的操作系统源代码、文档、第三方应用程序端口基础设施以及各种维护的实用程序。当分配 FreeBSD 提交位时,会指定该位可以在树的哪些区域使用。通常,与位关联的区域反映了授权分配提交位的实体。在稍后的日期,可能还会添加其他权限区域:当这种情况发生时,提交者应遵循该树区域的正常提交位分配程序,征求相关实体的批准,并可能在一段时间内为该区域获得导师。

提交者类型

负责

树组件

src

core@

src/

doc

doceng@

doc/、ports/、src/ 文档

ports

portmgr@

ports/

在开发权限区域概念之前分配的提交位可能适用于树的许多部分。但是,常识表明,以前没有在树的某个区域工作过的提交者在提交之前应该寻求审查,征求相关负责人的批准,或与导师一起工作。由于代码维护规则因树的区域而异,这既是为了在不太熟悉的区域工作提交者的利益,也是为了树上其他工作人员的利益。

无论工作在树的哪个区域,都鼓励提交者在正常开发过程中寻求对他们的工作进行审查。

4.1. 提交者在其他树中的活动政策

  • 所有提交者都可以修改 src/share/misc/committers-*.dotsrc/usr.bin/calendar/calendars/calendar.freebsdports/astro/xearth/files

  • doc 提交者可以提交对 src 文件的文档更改,例如手册页、自述文件、财富数据库、日历文件和注释修复,无需 src 提交者的批准,但需遵守正常的提交维护和管理。

  • 任何提交者都可以对任何其他树进行更改,但需要来自具有相应位的非指导提交者的“批准”。指导提交者可以提供“审核”,但不能提供“批准”。

  • 提交者可以通过通常的流程获得额外的位,即找到一位导师,该导师会建议他们加入 core、doceng 或 portmgr(视情况而定)。获得批准后,他们将被添加到“访问”,并开始正常的指导期,这将涉及在一段时间内持续“批准”。

4.1.1. 文档隐式(总体)批准

某些类型的修复具有来自文档工程团队 <doceng@FreeBSD.org> 的“总体批准”,允许任何提交者修复文档树任何部分的这些类别的错误。如果作者没有 doc 提交位,这些修复不需要来自 doc 提交者的批准或审查。

总体批准适用于以下类型的修复

  • 错别字

  • 微不足道的修复

    标点符号、URL、日期、路径和文件名可能包含过时或不正确的信息,以及其他可能使读者感到困惑的常见错误。

多年来,doc 树中获得了一些隐式批准。此列表显示了最常见的案例

在任何提交之前,都需要进行构建测试;有关更多详细信息,请参阅 FreeBSD 文档项目入门指南 的“概述”和“FreeBSD 文档构建流程”部分。

5. Git 入门

5.1. Git 基础

当搜索“Git 入门”时,会出现很多不错的入门指南。Daniel Miessler 的 Git 入门指南 和 Willie Willus 的 Git - 快速入门 都是很好的概述。Git 书籍也很全面,但篇幅较长 https://git-scm.cn/book/en/v2。还有一个网站 https://dangitgit.com/,介绍 Git 的常见陷阱和缺陷,以防您需要指导来修复问题。最后,一个针对计算机科学家的介绍 面向计算机科学家的 Git 入门 被证明对某些人解释 Git 世界观很有帮助。

本文档假设您已通读本文档,并尽量避免赘述基础知识(尽管会简要介绍它们)。

5.2. Git 简明入门

本入门指南的范围不如旧的 Subversion 入门指南那么大,但应该涵盖基础知识。

5.2.1. 范围

如果您想下载 FreeBSD,从源代码编译它,并通过这种方式保持最新,本入门指南适合您。它涵盖了获取源代码、更新源代码、二分搜索,并简要介绍了如何处理一些本地更改。它涵盖了基础知识,并尝试为读者在发现基础知识不足时提供更深入的处理方法的良好指针。本指南的其他部分涵盖了与为项目贡献相关更高级的主题。

本节的目的是突出显示跟踪源代码所需的那些 Git 部分。它们假设对 Git 有基本的了解。网络上有很多 Git 入门指南,但 Git 书籍 提供了更好的处理方法之一。

5.2.2. 开发人员入门

本节介绍了提交者从开发人员或贡献者推送提交的读写访问权限。

5.2.2.1. 日常使用

在以下示例中,将 ${repo} 替换为所需 FreeBSD 存储库的名称:docportssrc

  • 克隆存储库

    % git clone -o freebsd --config remote.freebsd.fetch='+refs/notes/*:refs/notes/*' https://git.freebsd.org/${repo}.git

    然后您应该将官方镜像作为您的远程存储库

    % git remote -v
    freebsd  https://git.freebsd.org/${repo}.git (fetch)
    freebsd  https://git.freebsd.org/${repo}.git (push)
  • 配置 FreeBSD 提交者数据

    repo.freebsd.org 中的提交钩子会检查“Commit”字段是否与 FreeBSD.org 中的提交者信息匹配。获得建议配置的最简单方法是在 freefall 上执行 /usr/local/bin/gen-gitconfig.sh 脚本

    % gen-gitconfig.sh
    [...]
    % git config user.name (your name in gecos)
    % git config user.email (your login)@FreeBSD.org
  • 设置推送 URL

    % git remote set-url --push freebsd git@gitrepo.freebsd.org:${repo}.git

    然后您应该将分离的获取和推送 URL 作为最有效的设置

    % git remote -v
    freebsd  https://git.freebsd.org/${repo}.git (fetch)
    freebsd  git@gitrepo.freebsd.org:${repo}.git (push)

    同样,请注意 gitrepo.freebsd.org 已规范化为 repo.freebsd.org

  • 安装提交消息模板钩子

    对于 doc 存储库

    % cd .git/hooks
    % ln -s ../../.hooks/prepare-commit-msg

    对于 ports 存储库

    % git config --add core.hooksPath .hooks

    对于 src 存储库

    % cd .git/hooks
    % ln -s ../../tools/tools/git/hooks/prepare-commit-msg
5.2.2.2. "admin" 分支

accessmentors 文件存储在每个存储库中的孤儿分支 internal/admin 中。

以下示例介绍了如何将 internal/admin 分支检出到名为 admin 的本地分支

% git config --add remote.freebsd.fetch '+refs/internal/*:refs/internal/*'
% git fetch
% git checkout -b admin internal/admin

或者,您可以为 admin 分支添加一个工作区

git worktree add -b admin ../${repo}-admin internal/admin

要在线浏览 internal/admin 分支:https://cgit.freebsd.org/${repo}/log/?h=internal/admin

对于推送,请指定完整 refspec

git push freebsd HEAD:refs/internal/admin

5.2.3. 与 FreeBSD src 树保持同步

第一步:克隆树。这将下载整个树。有两种下载方式。大多数人会想要对存储库进行深度克隆。但是,在某些情况下,您可能希望进行浅克隆。

5.2.3.1. 分支名称

FreeBSD-CURRENT 使用 main 分支。

main 是默认分支。

对于 FreeBSD-STABLE,分支名称包括 stable/12stable/13

对于 FreeBSD-RELEASE,版本工程分支名称包括 releng/12.4releng/13.2

  • mainstable/⋯ 分支打开

  • releng/⋯ 分支,每个分支在发布版本被标记时都会被冻结。

示例

5.2.3.2. 存储库

请参阅 管理详细信息 以获取有关从何处获取 FreeBSD 源代码的最新信息。以下的 $URL 可以从该页面获取。

注意:项目不使用子模块,因为它们不适合我们的工作流程和开发模型。我们在其他地方讨论了如何跟踪第三方应用程序中的更改,而这通常与普通用户无关。

5.2.3.3. 深度克隆

深度克隆会拉取整个树,以及所有历史记录和分支。这是最简单的方法。它还允许您使用 Git 的工作区功能将所有活动分支检出到单独的目录中,但只保留一个存储库副本。

% git clone -o freebsd $URL -b branch [<directory>]

 — 将创建一个深度克隆。branch 应该是上一节中列出的分支之一。如果未提供 branch:将使用默认分支 (main)。如果未提供 <directory>:新目录的名称将与存储库的名称匹配 (docportssrc).

如果您对历史记录感兴趣,计划进行本地更改或计划在多个分支上工作,您将需要深度克隆。它也是最容易保持最新状态的。如果您对历史记录感兴趣,但只在一个分支上工作并且空间不足,您也可以使用 --single-branch 只下载一个分支(尽管一些合并提交不会引用合并来源分支,这对于某些对历史记录详细版本感兴趣的用户来说可能很重要)。

5.2.3.4. 浅克隆

浅克隆只复制最新的代码,但没有或几乎没有历史记录。当您需要构建 FreeBSD 的特定版本,或者只是开始使用并计划更全面地跟踪树时,这很有用。您也可以使用它将历史记录限制为只有这么多修订版。但是,请参阅以下关于这种方法的重大限制。

% git clone -o freebsd -b branch --depth 1 $URL [dir]

这会克隆存储库,但只包含存储库中最新的版本。其余历史记录不会下载。如果您以后改变主意,可以执行 git fetch --unshallow 来获取旧的历史记录。

当您进行浅克隆时,您将在 uname 输出中丢失提交计数。这可能会使您在发布安全公告时更难确定您的系统是否需要更新。

5.2.3.5. 构建

下载后,构建就像手册中描述的那样完成,例如

% cd src
% make buildworld
% make buildkernel
% make installkernel
% make installworld

因此,这里不会深入介绍。

如果您想构建自定义内核,FreeBSD 手册的内核配置部分 建议在 sys/${ARCH}/conf 下创建一个名为 MYKERNEL 的文件,其中包含您对 GENERIC 的更改。要使 Git 忽略 MYKERNEL,可以将其添加到 .git/info/exclude 中。

5.2.3.6. 更新

要更新这两种类型的树,使用相同的命令。这将拉取自上次更新以来的所有修订版。

% git pull --ff-only

将更新树。在 Git 中,“快进”合并是指只需设置一个新的分支指针而无需重新创建提交的合并。通过始终执行快进合并/拉取,您可以确保拥有 FreeBSD 树的精确副本。如果您想维护本地补丁,这一点很重要。

请参阅以下有关如何管理本地更改的信息。最简单的方法是在 git pull 命令中使用 --autostash,但还有更复杂的选择可用。

5.2.4. 选择特定版本

在 Git 中,git checkout 既可以检出分支,也可以检出特定版本。Git 的版本是长哈希,而不是顺序编号。

当您检出特定版本时,只需在命令行中指定所需的哈希值(git log 命令可以帮助您确定您可能需要的哈希值)

% git checkout 08b8197a74

然后您就检出了该版本。您将收到类似于以下内容的消息

Note: checking out '08b8197a742a96964d2924391bf9fdfeb788865d'.

You are in a 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 08b8197a742a hook gpiokeys.4 to the build

其中最后一行是由您要检出的哈希值和该修订版本的提交消息的第一行生成的。哈希值可以缩写为最短的唯一长度。Git 本身在显示位数方面并不一致。

5.2.5. 二分查找

有时,事情会出错。最后一个版本有效,但您刚刚更新的版本无效。开发人员可能会要求您对问题进行二分查找,以跟踪哪个提交导致了回归。

Git 使用强大的 git bisect 命令使二分查找更改变得容易。以下是使用它的简要概述。有关更多信息,您可以查看 https://www.metaltoad.com/blog/beginners-guide-git-bisect-process-eliminationhttps://git-scm.cn/docs/git-bisect 以获取更多详细信息。git-bisect 手册页面擅长描述可能出现的问题,例如版本无法构建时该怎么办,当您想使用“好”和“坏”以外的术语时该怎么办等等,这里不会介绍这些内容。

git bisect start --first-parent 将启动二分查找过程。接下来,您需要告诉它要遍历的范围。git bisect good XXXXXX 将告诉它工作版本,而 git bisect bad XXXXX 将告诉它错误版本。错误版本几乎总是 HEAD(您检出的内容的特殊标签)。良好版本将是您最后检出的版本。--first-parent 参数是必要的,这样后续的 git bisect 命令就不会尝试检出缺少完整 FreeBSD 源代码树的供应商分支。

如果您想知道您最后检出的版本,您应该使用 git reflog

5ef0bd68b515 (HEAD -> main, freebsd/main, freebsd/HEAD) HEAD@{0}: pull --ff-only: Fast-forward
a8163e165c5b (upstream/main) HEAD@{1}: checkout: moving from b6fb97efb682994f59b21fe4efb3fcfc0e5b9eeb to main
...

显示我将工作树移动到 main 分支 (a816…​),然后从上游更新 (到 5ef0…​)。在这种情况下,bad 将是 HEAD(或 5ef0bd68b515),good 将是 a8163e165c5b。从输出中可以看出,HEAD@{1} 也经常有效,但如果您在更新后但在发现需要二分查找之前对您的 Git 树进行了其他操作,它就不灵验了。

先设置“好”版本,然后设置“坏”版本(虽然顺序并不重要)。当您设置错误版本时,它会给您一些关于该过程的统计信息

% git bisect start --first-parent
% git bisect good a8163e165c5b
% git bisect bad HEAD
Bisecting: 1722 revisions left to test after this (roughly 11 steps)
[c427b3158fd8225f6afc09e7e6f62326f9e4de7e] Fixup r361997 by balancing parens.  Duh.

然后您将构建/安装该版本。如果它有效,您将键入 git bisect good,否则键入 git bisect bad。如果该版本无法编译,请键入 git bisect skip。您将在每个步骤之后收到类似于上面的消息。完成后,将错误版本报告给开发人员(或者自己修复错误并发送补丁)。git bisect reset 将结束该过程,并让您回到开始的地方(通常是 main 的顶端)。同样,git-bisect 手册(上面链接)是出现问题或遇到特殊情况时的良好资源。

5.2.6. 使用 GnuPG 签署提交、标签和推送

Git 知道如何签署提交、标签和推送。当您签署 Git 提交或标签时,您可以证明您提交的代码来自您,并且在您传输时没有被更改。您还可以证明是您提交的代码,而不是其他人。

有关签署提交和标签的更深入文档,可以在 Git 手册的 Git 工具 - 签署您的工作 章中找到。

签署推送背后的基本原理可以在 引入该功能的提交 中找到。

最好的方法是简单地告诉 Git 您始终希望签署提交、标签和推送。您可以通过设置一些配置变量来做到这一点

% git config --add user.signingKey LONG-KEY-ID
% git config --add commit.gpgSign true
% git config --add tag.gpgSign true
% git config --add push.gpgSign if-asked

为了避免可能的冲突,请确保您向 Git 提供一个长的密钥 ID。您可以使用以下命令获取长 ID:gpg --list-secret-keys --keyid-format LONG

要使用特定的子密钥,而不是让 GnuPG 将子密钥解析为主密钥,请在密钥后面附加 !。例如,要使用子密钥 DEADBEEF 进行加密,请使用 DEADBEEF!

5.2.6.1. 验证签名

可以通过运行 git verify-commit <commit hash>git log --show-signature 来验证提交签名。

可以使用 git verify-tag <tag name>git tag -v <tag name> 来验证标签签名。

5.2.7. 端口注意事项

端口树的工作方式相同。分支名称不同,存储库位于不同的位置。

用于 Web 浏览器的 cgit 存储库 Web 界面位于 https://cgit.FreeBSD.org/ports/ 。生产 Git 存储库位于 https://git.FreeBSD.org/ports.git 以及 ssh://anongit@git.FreeBSD.org/ports.git(或 anongit@git.FreeBSD.org:ports.git)。

GitHub 上也有一面镜像,请参阅 外部镜像 以获取概述。最新分支是 main季度分支命名为 yyyyQn,其中 'yyyy' 是年份,'n' 是季度。

5.2.7.1. 提交消息格式

端口存储库中提供了一个钩子,可帮助您以 .hooks/prepare-commit-message 的格式编写提交消息。可以通过运行 git config --add core.hooksPath .hooks 来启用它。

主要观点是提交消息应按以下方式格式化

category/port: Summary.

Description of why the changes where made.

PR:	    12345

第一行是提交的主题,它包含更改了哪个端口以及提交的摘要。它应该包含 50 个字符或更少。

一行空行应将其与提交消息的其余部分隔开。

提交消息的其余部分应在 72 个字符的边界处换行。

如果存在任何元数据字段,则应添加另一行空行,以便它们与提交消息很容易区分。

5.2.8. 管理本地更改

本节讨论跟踪本地更改。如果您没有本地更改,则可以跳过本节。

所有更改都非常重要的一点:所有更改在推送之前都是本地的。与 Subversion 不同,Git 使用分布式模型。对于用户来说,对于大多数事情来说,差别很小。但是,如果您有本地更改,您可以使用与用于从 FreeBSD 中提取更改相同的工具来管理它们。您未推送的所有更改都是本地的,并且可以轻松地进行修改(下面将讨论的 git rebase 会执行此操作)。

5.2.8.1. 保留本地更改

保留本地更改(尤其是微不足道的更改)的最简单方法是使用 git stash。在最简单的形式中,您使用 git stash 来记录更改(将其推送到隐藏栈上)。大多数人使用它来保存更改,然后再按照上述方法更新树。然后他们使用 git stash apply 将它们重新应用于树。隐藏栈是更改的栈,可以使用 git stash list 检查。git-stash 手册页面 (https://git-scm.cn/docs/git-stash) 包含所有详细信息。

此方法适用于您对树进行微调的情况。如果您有非微不足道的更改,那么您最好保留一个本地分支并进行变基。隐藏栈还与 git pull 命令集成在一起:只需在命令行中添加 --autostash 即可。

5.2.8.2. 保留本地分支

使用 Git 保留本地分支比使用 Subversion 容易得多。在 Subversion 中,您需要合并提交并解决冲突。这可以管理,但会导致复杂的提交历史,这可能难以向上游迁移(如果确实需要),或者难以复制(如果您需要这样做)。Git 还允许您合并,并带来同样的问题。这是管理分支的一种方式,但它是最不灵活的方式。

除了合并之外,Git 还支持“变基”的概念,它避免了这些问题。git rebase 命令在父分支的新位置重播分支的所有提交。我们将介绍使用它时最常见的场景。

5.2.8.2.1. 创建分支

假设您想对 FreeBSD 的 ls 命令进行更改,使其永远不会进行颜色处理。有很多理由这样做,但此示例将使用它作为基线。FreeBSD ls 命令会不时地更改,您需要应对这些更改。幸运的是,使用 Git 变基,它通常是自动的。

% cd src
% git checkout main
% git checkout -b no-color-ls
% cd bin/ls
% vi ls.c     # hack the changes in
% git diff    # check the changes
diff --git a/bin/ls/ls.c b/bin/ls/ls.c
index 7378268867ef..cfc3f4342531 100644
--- a/bin/ls/ls.c
+++ b/bin/ls/ls.c
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#undef COLORLS
 #ifdef COLORLS
 #include <termcap.h>
 #include <signal.h>
% # these look good, make the commit...
% git commit ls.c

该提交会将您带入编辑器,以描述您所做的工作。输入后,您就在 Git 存储库中有了自己的**本地**分支。按照手册中的说明构建和安装它,就像您平常一样。Git 与其他版本控制系统不同,您必须明确地告诉它要提交哪些文件。我选择在提交命令行上执行此操作,但您也可以使用 git add 执行此操作,许多更深入的教程都介绍了这一点。

5.2.8.2.2. 更新时间

当需要引入新版本时,它与没有分支的情况几乎相同。您将像上面一样更新,但更新之前有一个额外的命令,更新之后也有一条命令。以下假设您从一个未修改的树开始。在开始变基操作之前,重要的是要使用一个干净的树(Git 需要这样)。

% git checkout main
% git pull --ff-only
% git rebase -i main no-color-ls

这会弹出一个编辑器,其中列出了其中的所有提交。在此示例中,请勿进行任何更改。这通常是您在更新基线时所做的操作(尽管您也可以使用 Git 变基命令来整理分支中的提交)。

完成上述操作后,您必须将 ls.c 中的提交从 FreeBSD 的旧版本向前移动到较新的版本。

有时会出现合并冲突。这没关系。不要惊慌。相反,按照处理其他任何合并冲突的方式处理它们。为了简单起见,我将只描述可能出现的常见问题。在本节末尾可以找到对完整处理的指针。

假设包括在终端信息方面发生了根本性变化,并且选项名称也发生了更改。当您更新时,您可能会看到类似以下内容

Auto-merging bin/ls/ls.c
CONFLICT (content): Merge conflict in bin/ls/ls.c
error: could not apply 646e0f9cda11... no color ls
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 646e0f9cda11... no color ls

看起来很吓人。如果您打开一个编辑器,您会看到它是一个典型的 3 路合并冲突解决,您可能从其他源代码系统中熟悉(ls.c 的其余部分已省略)

 <<<<<<< HEAD
 #ifdef COLORLS_NEW
 #include <terminfo.h>
 =======
 #undef COLORLS
 #ifdef COLORLS
 #include <termcap.h>
 >>>>>>> 646e0f9cda11... no color ls
....
The new code is first, and your code is second.
The right fix here is to just add a #undef COLORLS_NEW before #ifdef and then delete the old changes:
[source,shell]
....
#undef COLORLS_NEW
#ifdef COLORLS_NEW
#include <terminfo.h>
....
save the file.
The rebase was interrupted, so you have to complete it:
[source,shell]
....
% git add ls.c
% git rebase --continue
....

这告诉 Git ls.c 已被修复,并继续变基操作。由于出现了冲突,您将被踢回编辑器以根据需要更新提交消息。如果提交消息仍然准确,只需退出编辑器即可。

如果您在变基过程中卡住了,不要惊慌。git rebase --abort 会让您回到干净的状态。但是,重要的是要从一个未修改的树开始。顺便说一句:上面提到的 git reflog 在这里很有用,因为它会包含您所有(中间)提交的列表,您可以查看、检查或挑选这些提交。

有关此主题的更多信息,https://www.freecodecamp.org/news/the-ultimate-guide-to-git-merge-and-git-rebase/ 提供了相当广泛的处理方法。对于偶尔出现但过于模糊而无法在本指南中介绍的问题,它是一个很好的资源。

5.2.8.3. 切换到不同的 FreeBSD 分支

如果您希望从 stable/12 切换到当前分支。如果您有一个深度克隆,以下步骤就足够了

% git checkout main
% # build and install here...

但是,如果您有本地分支,则存在一两个注意事项。首先,rebase 会重写历史记录,因此您可能需要执行某些操作来保存它。其次,跳跃分支往往会导致更多冲突。如果我们假设上面的示例相对于 stable/12,那么要切换到 `main`,我建议执行以下操作

% git checkout no-color-ls
% git checkout -b no-color-ls-stable-12   # create another name for this branch
% git rebase -i stable/12 no-color-ls --onto main

上面的操作会检出 no-color-ls。然后为它创建一个新名称 (no-color-ls-stable-12),以防您需要返回到它。然后您将 rebase 到 `main` 分支。这将找到当前 no-color-ls 分支的所有提交 (回到它与 stable/12 分支相遇的地方),然后它将在 `main` 分支上重播它们,在那里创建一个新的 no-color-ls 分支 (这就是我让您创建一个占位符名称的原因)。

5.3. MFC (从当前合并) 程序

5.3.1. 摘要

MFC 工作流程可以概括为 `git cherry-pick -x` 加上 `git commit --amend` 来调整提交消息。对于多个提交,使用 `git rebase -i` 将它们压缩在一起并编辑提交消息。

5.3.2. 单个提交 MFC

% git checkout stable/X
% git cherry-pick -x $HASH --edit

对于 MFC 提交,例如供应商导入,您需要为 cherry-pick 目的指定一个父项。通常,这将是您从中 cherry-pick 的分支的“第一个父项”,因此

% git checkout stable/X
% git cherry-pick -x $HASH -m 1 --edit

如果出现错误,您将需要使用 `git cherry-pick --abort` 终止 cherry-pick 或修复它并执行 `git cherry-pick --continue`。

cherry-pick 完成后,使用 `git push` 推送。如果您由于丢失提交竞赛而收到错误,请使用 `git pull --rebase` 并尝试再次推送。

5.3.3. MFC 到 RELENG 分支

需要批准的分支的 MFC 需要更加小心。无论是典型的合并还是特殊的直接提交,流程都是相同的。

  • 首先合并或直接提交到相应的 `stable/X` 分支,然后再合并到 `releng/X.Y` 分支。

  • 使用 `stable/X` 分支中的哈希值将 MFC 合并到 `releng/X.Y` 分支。

  • 在提交消息中保留两个“从...cherry-pick”行。

  • 在编辑器中时,请务必添加 `Approved by:` 行。

% git checkout releng/13.0
% git cherry-pick -x $HASH --edit

如果您忘记添加 `Approved by:` 行,您可以在推送更改之前执行 `git commit --amend` 来编辑提交消息。

5.3.4. 多个提交 MFC

% git checkout -b tmp-branch stable/X
% for h in $HASH_LIST; do git cherry-pick -x $h; done
% git rebase -i stable/X
# mark each of the commits after the first as 'squash'
# Update the commit message to reflect all elements of commit, if necessary.
# Be sure to retain the "cherry picked from" lines.
% git push freebsd HEAD:stable/X

如果推送由于丢失提交竞赛而失败,请重新 rebase 并重试

% git checkout stable/X
% git pull
% git checkout tmp-branch
% git rebase stable/X
% git push freebsd HEAD:stable/X

MFC 完成后,您可以删除临时分支

% git checkout stable/X
% git branch -d tmp-branch

5.3.5. MFC 供应商导入

供应商导入是树中唯一在 `main` 分支中创建合并提交的内容。将合并提交 cherry-pick 到 stable/XX 会带来额外的困难,因为合并提交有两个父项。通常,您需要第一个父项的 diff,因为它是到 `main` 的 diff (尽管可能存在一些例外)。

% git cherry-pick -x -m 1 $HASH

通常是您想要的。这将告诉 cherry-pick 应用正确的 diff。

存在一些(希望是罕见的)情况,即 `main` 分支可能被转换脚本反向合并。如果出现这种情况 (我们还没有发现任何情况),您需要将上面的更改为 `-m 2` 以选择正确的父项。只需执行

% git cherry-pick --abort
% git cherry-pick -x -m 2 $HASH

即可完成此操作。`--abort` 将清理第一次失败的尝试。

5.3.6. 重新执行 MFC

如果您执行 MFC,结果非常糟糕,并且您想要重新开始,那么最简单的方法是使用 `git reset --hard`,如下所示

% git reset --hard freebsd/stable/12

但是,如果您有一些想要保留的版本,而另一些版本则不需要,那么使用 `git rebase -i` 会更好。

5.3.7. MFC 时需要考虑的事项

将源代码提交到 stable 和 releng 分支时,我们有以下目标

  • 明确标记从其他分支着陆更改的提交与直接提交之间的区别。

  • 避免将已知的故障引入 stable 和 releng 分支。

  • 允许开发人员确定哪些更改已从一个分支着陆到另一个分支,哪些更改尚未着陆。

使用 Subversion 时,我们使用以下做法来实现这些目标

  • 使用 `MFC` 和 `MFS` 标签标记从另一个分支合并的更改。

  • 在合并更改时将修复提交压缩到主提交中。

  • 记录合并信息,以便 `svn mergeinfo --show-revs` 可以工作。

使用 Git 时,我们需要使用不同的策略来实现相同的目标。本文档旨在定义使用 Git 合并源代码提交时的最佳实践,以实现这些目标。通常,我们旨在使用 Git 的原生支持来实现这些目标,而不是强制执行基于 Subversion 模型的实践。

一般说明:由于 Git 的技术差异,我们不会在 stable 或 releng 分支中使用 Git 的“合并提交”(通过 `git merge` 创建)。相反,当本文档提到“合并提交”时,指的是最初提交到 `main` 的提交,它被复制或“着陆”到 stable 分支,或者来自 stable 分支的提交,它被复制到 releng 分支,并使用 `git cherry-pick` 的某种变体。

5.3.8. 查找可用于 MFC 的哈希值

Git 通过 `git cherry` 和 `git log --cherry` 命令提供了一些内置支持。这些命令比较提交的原始 diff (但不是其他元数据,例如日志消息) 以确定两个提交是否相同。当来自 `main` 的每个提交都被作为单个提交着陆到 stable 分支时,这非常有效,但是如果来自 `main` 的多个提交被压缩在一起作为单个提交着陆到 stable 分支,则会失效。该项目广泛使用 `git cherry-pick -x` 并保留所有行来解决这些困难,并且正在努力开发利用此功能的自动化工具。

5.3.9. 提交消息标准

5.3.9.1. 标记 MFC

该项目已采用以下做法来标记 MFC

  • 将 `-x` 标记与 `git cherry-pick` 一起使用。这会将一行添加到提交消息中,其中包含合并时原始提交的哈希值。由于它是 Git 直接添加的,因此提交者在合并时无需手动编辑提交日志。

合并多个提交时,保留所有“从...cherry-pick”行。

5.3.9.2. 修剪元数据?

Subversion (甚至 CVS) 没有清楚地记录如何为 MFC 提交的日志消息格式化元数据。它是否应该包含原始提交的元数据而不做更改,还是应该更改以反映 MFC 提交本身的信息?

历史做法各不相同,尽管部分差异是按字段划分的。例如,与 PR 相关的 MFC 通常会在 MFC 中包含 PR 字段,以便 MFC 提交包含在错误跟踪器的审计跟踪中。其他字段不太清楚。例如,Phabricator 显示与评审标记的最后一个提交的 diff,因此包含 Phabricator URL 会将主提交替换为已着陆的提交。审阅者列表也不清楚。如果审阅者已批准对 `main` 的更改,是否意味着他们已批准 MFC 提交?如果只是相同的代码,或者仅仅是微不足道的返工,是否属实?对于更广泛的返工来说,这显然不属实。即使对于相同的代码,如果提交没有冲突,但引入了 ABI 更改呢?审阅者可能已批准对 `main` 的提交,原因是 ABI 出现故障,但可能不批准按原样合并相同的提交。在达成明确的指南之前,您将不得不使用您最好的判断力。

对于受 re@ 监管的 MFC,会添加新的元数据字段,例如已批准提交的 Approved by 标签。此新的元数据将必须在原始提交经过评审和批准后通过 `git commit --amend` 或类似方式添加。我们也可能想要为 MFC 提交保留一些元数据字段,例如 Phabricator URL,供 re@ 将来使用。

保留现有元数据提供了一个非常简单的流程。开发人员使用 `git cherry-pick -x`,无需编辑日志消息。

相反,如果我们选择调整 MFC 中的元数据,开发人员将必须通过使用 `git cherry-pick --edit` 或 `git commit --amend` 明确地编辑日志消息。但是,与 svn 相比,至少现有的提交消息可以预先填充,并且可以添加或删除元数据字段,而无需重新输入整个提交消息。

底线是,开发人员可能需要为非平凡的 MFC 策划他们的提交消息。

5.4. 使用 Git 进行供应商导入

本节详细介绍了使用 Git 进行供应商导入的过程。

5.4.1. 分支命名约定

所有供应商分支和标签都以 `vendor/` 开头。这些分支和标签默认情况下可见。

本章遵循这样的约定,即 `freebsd` 来源是官方 FreeBSD Git 存储库的来源名称。如果您使用不同的约定,请在下面的示例中将 `freebsd` 替换为您使用的名称。

我们将探索一个更新我们树中 NetBSD 的 mtree 的示例。此供应商分支为 `vendor/NetBSD/mtree`。

5.4.2. 更新旧的供应商导入

供应商树通常只包含适合 FreeBSD 的第三方软件子集。这些树通常比 FreeBSD 树小得多。因此,Git 工作树非常小且快速,并且是首选方法。确保您在下面选择的任何目录 (../mtree) 目前不存在。

% git worktree add ../mtree vendor/NetBSD/mtree

5.4.3. 更新供应商分支中的来源

准备一个完整的、干净的供应商来源树。导入所有内容,但只合并所需的内容。

此示例假设 NetBSD 源代码是从他们的 GitHub 镜像 `~/git/NetBSD` 中检出的。请注意,“上游”可能已添加或删除文件,因此我们要确保删除操作也得到传播。 net/rsync 通常已安装,因此我将使用它。

% cd ../mtree
% rsync -va --del --exclude=".git" ~/git/NetBSD/usr.sbin/mtree/ .
% git add -A
% git status
...
% git diff --staged
...
% git commit -m "Vendor import of NetBSD's mtree at 2020-12-11"
[vendor/NetBSD/mtree 8e7aa25fcf1] Vendor import of NetBSD's mtree at 2020-12-11
 7 files changed, 114 insertions(+), 82 deletions(-)
% git tag -a vendor/NetBSD/mtree/20201211

务必验证您要导入的源代码来自可信来源。许多开源项目使用加密签名来签署代码更改、git 标签和/或源代码 tarball。始终验证这些签名,并使用隔离机制(如 jail、chroot)以及与您经常使用的帐户不同的专用非特权用户帐户(有关详细信息,请参见下面的更新 FreeBSD 源代码树部分),直到您确信要导入的源代码看起来安全。跟踪上游开发并偶尔审查上游代码更改可以极大地帮助提高代码质量,并使所有相关人员受益。在将更改导入供应商区域之前,检查 git diff 结果也是一个好主意。

始终运行 git diffgit status 命令,并仔细检查结果。如有疑问,对供应商分支或上游 git 存储库执行 git annotate 以查看更改是由谁进行的以及更改的原因。

在上面的示例中,我们使用了 -m 进行说明,但您应该在编辑器中(使用提交消息模板)编写一条合适的提交消息。

使用 git tag -a 创建带注释的标签也很重要,否则推送将被拒绝。只允许推送带注释的标签。带注释的标签为您提供了输入提交消息的机会。输入您要导入的版本,以及该版本中的任何重要新功能或修复。

5.4.4. 更新 FreeBSD 副本

此时,您可以将导入推送到我们的存储库中的 vendor 分支。

% git push --follow-tags freebsd vendor/NetBSD/mtree

--follow-tags 告诉 git push 也推送与本地提交的修订版关联的标签。

5.4.5. 更新 FreeBSD 源代码树

现在,您需要更新 FreeBSD 中的 mtree。源代码位于 contrib/mtree 中,因为它来自上游软件。

有时,我们可能需要对贡献的代码进行更改以更好地满足 FreeBSD 的需求。如果可能,请尝试将本地更改贡献回上游项目,这将帮助他们更好地支持 FreeBSD,并节省您在导入更新时将来解决冲突的时间。

% cd ../src
% git subtree merge -P contrib/mtree vendor/NetBSD/mtree

这将生成 contrib/mtree 相对于本地 vendor/NetBSD/mtree 分支的子树合并提交。检查合并结果的 diff 和上游分支的内容。如果合并将我们本地的更改缩减为更简单的差异(如空行或缩进更改),请尝试修改本地更改以减少相对于上游的 diff,或尝试将剩余的更改贡献回上游项目。如果存在冲突,您需要在提交之前解决冲突。在合并提交消息中包含有关正在合并的更改的详细信息。

一些开源软件包含一个 configure 脚本,该脚本生成用于定义代码构建方式的文件;通常,这些生成的文件(如 config.h)应该作为导入过程的一部分进行更新。在执行此操作时,请始终牢记,这些脚本是在当前用户的凭据下运行的可执行代码。此过程应始终在隔离的环境中运行,理想情况下是在没有网络访问权限的 jail 中,并使用非特权帐户;或者,至少使用一个专用的帐户,该帐户不同于您通常用于日常目的或将代码推送到 FreeBSD 源代码存储库的帐户。这最大限度地降低了遇到可能导致数据丢失或在更糟的情况下,恶意植入的代码的错误的风险。使用隔离的 jail 还可以防止 configure 脚本检测到本地安装的软件包,这可能会导致意外结果。

在测试您的更改时,请首先在 chroot 或 jail 环境中运行它们,甚至在虚拟机中运行它们,特别是对于内核或库修改。这种方法有助于防止与您的工作环境发生不良交互。对于许多基本系统组件使用的库的更改,它尤其有用。

5.4.6. 将您的更改重新基准到最新的 FreeBSD 源代码树

由于当前策略建议不要使用合并,如果在您有机会推送之前,上游 FreeBSD main 继续前进,则您将不得不重新进行合并。

常规 git rebasegit pull --rebase 不知道如何将合并提交作为合并提交重新基准,因此您将不得不重新创建提交,而不是这样做。

应采取以下步骤来轻松重新创建合并提交,就像 git rebase --merge-commits 正确工作一样。

  • cd 到存储库的顶部

  • 使用合并树的内容创建一个名为 XXX 的分支。

  • 更新此分支 XXX 以便与 FreeBSD 的 main 分支合并并保持最新。

    • 在最坏的情况下,您仍然需要解决合并冲突(如果有),但这应该非常罕见。

    • 解决冲突,并将多个提交折叠为 1 个(如果没有冲突,则不需要折叠)

  • 检出 main

  • 创建一个名为 YYY 的分支(允许在出现错误时更容易撤消)

  • 重新执行子树合并

  • 不要解决子树合并中的任何冲突,而是将其内容检出到 XXX 之上。

    • 最后的 . 很重要,就像位于存储库的顶层一样。

    • 它不会切换到 XXX 分支,而是将 XXX 的内容附加到存储库的顶部。

  • 使用先前的提交消息提交结果(该示例假设 XXX 分支上只有一个合并)。

  • 确保分支相同。

  • 进行您需要的任何审查,包括让其他人检出,如果您认为有必要。

  • 推送提交,如果您再次“输掉了比赛”,只需再次执行这些步骤(有关食谱,请参见下文)

  • 一旦提交上游,就删除这些分支。它们是临时的。

您将使用的命令,遵循上面 mtree 的示例,如下所示(# 表示注释,以帮助将命令链接到上面的描述)

% cd ../src			# CD to top of tree
% git checkout -b XXX		# create new throw-away XXX branch for merge
% git fetch freebsd		# Get changes from upstream from upstream
% git merge freebsd/main	# Merge the changes and resolve conflicts
% git checkout -b YYY freebsd/main # Create new throw-away YYY branch for redo
% git subtree merge -P contrib/mtree vendor/NetBSD/mtree # Redo subtree merge
% git checkout XXX .		# XXX branch has the conflict resolution
% git commit -c XXX~1		# -c reuses the commit message from commit before rebase
% git diff XXX YYY		# Should be empty
% git show YYY			# Should only have changes you want, and be a merge commit from vendor branch

注意:如果提交出现问题,您可以通过重新发布创建它的检出命令来重置 YYY 分支,并使用 -B 从头开始

% git checkout -B YYY freebsd/main # Create new throw-away YYY branch if starting over is just going to be easier

5.4.7. 推送更改

一旦您认为自己有一组好的更改,就可以将其推送到 GitHub 或 GitLab 的分支中,供其他人审查。Git 的一个好处是,它允许您发布工作草稿以供其他人审查。虽然 Phabricator 很适合内容审查,但发布更新的供应商分支和合并提交可以使其他人检查详细信息,因为这些详细信息最终将出现在存储库中。

经过审查后,当您确信这是一个好的更改时,您可以将其推送到 FreeBSD 存储库。

% git push freebsd YYY:main	# put the commit on upstream's 'main' branch
% git branch -D XXX		# Throw away the throw-a-way branches.
% git branch -D YYY

注意:我使用 XXXYYY 来明确它们是糟糕的名称,不应该离开您的机器。如果您在其他工作中使用这些名称,那么您将需要选择不同的名称,否则您可能会丢失其他工作。这些名称没有什么神奇之处。上游将不允许您推送它们,但无论如何,请注意上面的确切命令。某些命令使用的语法与典型用法略有不同,并且这种不同的行为对于此食谱的正常工作至关重要。

5.4.8. 如何在需要时重新执行操作

如果您尝试执行上一节中的推送操作,但失败了,则应执行以下操作来“重新执行”操作。此序列将始终使提交与提交消息保持在 XXX~1,以方便提交。

% git checkout -B XXX YYY	# recreate that throw-away-branch XXX and switch to it
% git merge freebsd/main	# Merge the changes and resolve conflicts
% git checkout -B YYY freebsd/main # Recreate new throw-away YYY branch for redo
% git subtree merge -P contrib/mtree vendor/NetBSD/mtree # Redo subtree merge
% git checkout XXX .		# XXX branch has the conflict resolution
% git commit -c XXX~1		# -c reuses the commit message from commit before rebase

然后像上面一样检出,并在准备好时像上面一样推送。

5.5. 创建新的供应商分支

创建新的供应商分支的方法有很多种。推荐的方法是创建一个新的存储库,然后将其与 FreeBSD 合并。如果有人将 glorbnitz 导入 FreeBSD 树中,则版本为 3.1415。为了简单起见,我们不会修剪此版本。它是一个简单的用户命令,将 nitz 设备置于不同的神奇 glorb 状态,并且它足够小,修剪不会节省太多。

5.5.1. 创建存储库

% cd /some/where
% mkdir glorbnitz
% cd glorbnitz
% git init
% git checkout -b vendor/glorbnitz

此时,您拥有一个新的存储库,所有新的提交都将在 vendor/glorbnitz 分支上进行。

Git 专家也可以直接在他们的 FreeBSD 克隆中执行此操作,如果他们更习惯于使用 git checkout --orphan vendor/glorbnitz 的话。

5.5.2. 复制源代码

由于这是一个新的导入,您可以直接将源代码复制进来,或者使用 tar 甚至 rsync,如上所示。我们将添加所有内容,假设没有点文件。

% cp -r ~/glorbnitz/* .
% git add *

此时,您应该拥有一个原始的 glorbnitz 副本,可以准备提交。

% git commit -m "Import GlorbNitz frobnosticator revision 3.1415"

如上所示,我使用了 -m 来简化操作,但您应该创建一个提交消息来解释什么是 Glorb 以及为什么要使用 Nitz 来获取它。并非每个人都知道这一点,因此,在您的实际提交中,您应该遵循 提交日志消息 部分,而不是模仿此处使用的简短风格。

5.5.3. 现在将其导入我们的存储库

现在,您需要将分支导入我们的存储库。

% cd /path/to/freebsd/repo/src
% git remote add glorbnitz /some/where/glorbnitz
% git fetch glorbnitz vendor/glorbnitz

请注意,vendor/glorbnitz 分支位于存储库中。此时,如果您愿意,可以删除 /some/where/glorbnitz。它仅仅是一种手段而已。

5.5.4. 打标签和推送

从这里开始的步骤与更新供应商分支的步骤非常相似,只是没有更新供应商分支的步骤。

% git worktree add ../glorbnitz vendor/glorbnitz
% cd ../glorbnitz
% git tag --annotate vendor/glorbnitz/3.1415
# Make sure the commit is good with "git show"
% git push --follow-tags freebsd vendor/glorbnitz

我们所说的“好”是指:

  1. 所有正确文件都存在

  2. 不存在任何错误文件

  3. 供应商分支指向合理的内容

  4. 标签看起来不错,并且是带注释的

  5. 标签的提交消息包含自上次标签以来的新功能的简要摘要

5.5.5. 最后将其合并到基本树中

% cd ../src
% git subtree add -P contrib/glorbnitz vendor/glorbnitz
# Make sure the commit is good with "git show"
% git commit --amend   # one last sanity check on commit message
% git push freebsd

这里的“好”是指:

  1. 所有正确文件(以及所有错误文件)都已合并到 contrib/glorbnitz 中。

  2. 树中没有其他更改。

  3. 提交消息看起来 不错。它应该包含自上次合并到 FreeBSD main 分支以来的更改摘要以及任何注意事项。

  4. 如果存在任何值得注意的内容,例如用户可见的更改、重要的升级问题等,则应更新 UPDATING。

这还没有将 glorbnitz 连接到构建中。如何做到这一点取决于要导入的软件,超出了本教程的范围。

5.5.5.1. 保持最新

因此,时间流逝。现在该更新树以包含上游的最新更改了。当您检出 main 时,请确保您没有任何差异。在执行以下操作之前,将它们提交到分支(或使用 git stash)要容易得多。

如果您习惯使用git pull,我们强烈建议您使用--ff-only选项,并将其设置为默认选项。或者,如果您在main分支中有更改已暂存,则git pull --rebase很有用。

% git config --global pull.ff only

如果您希望此设置仅应用于此仓库,则可能需要省略--global。

% cd freebsd-src
% git checkout main
% git pull (--ff-only|--rebase)

有一个常见的陷阱,组合命令git pull将尝试执行合并,这有时会创建之前不存在的合并提交。这可能更难恢复。

也建议使用较长的形式。

% cd freebsd-src
% git checkout main
% git fetch freebsd
% git merge --ff-only freebsd/main

这些命令将您的树重置到main分支,然后从您最初拉取树的位置更新它。在执行此操作之前切换到main很重要,这样它才会向前移动。现在,是时候将更改向前移动了。

% git rebase -i main working

这将打开一个交互式屏幕以更改默认值。现在,只需退出编辑器即可。一切应该都适用。如果没有,则需要解决差异。 此github文档 可以帮助您浏览此过程。

5.5.5.2. 现在将更改推送到上游

首先,确保已为上游仓库正确配置了推送 URL。

% git remote set-url --push freebsd ssh://git@gitrepo.freebsd.org/src.git

然后,验证用户名和电子邮件是否配置正确。我们要求它们与 FreeBSD 集群中的 passwd 条目完全匹配。

使用

freefall% gen-gitconfig.sh

在 freefall.freebsd.org 上获取您可以直接使用的配方,假设 /usr/local/bin 在 PATH 中。

以下命令将working分支合并到上游main分支。在执行此操作之前,您务必整理好您的更改,使其与您希望它们在 FreeBSD 源代码库中的方式相同。此语法将working分支推送到main,将main分支向前移动。只有在对main进行线性更改(例如,没有合并)时,您才能执行此操作。

% git push freebsd working:main

如果由于丢失提交竞赛而导致推送被拒绝,请在再次尝试之前重新设置您的分支。

% git checkout working
% git fetch freebsd
% git rebase freebsd/main
% git push freebsd working:main
5.5.5.3. 现在将更改推送到上游(替代方法)

有些人发现将更改合并到本地main,然后再推送到远程仓库会更容易。此外,当您需要执行分支的子集时,git arc stage 会将更改从分支移动到本地main。说明类似于上一节。

% git checkout main
% git merge --ff-only `working`
% git push freebsd

如果输掉了竞赛,请再次尝试使用

% git pull --rebase
% git push freebsd

这些命令将获取最新的freebsd/main,然后在该基础上重新设置本地main更改,这就是在输掉提交竞赛时想要做的。注意:使用此技术不会合并供应商分支提交。

5.5.5.4. 查找 Subversion 版本

您需要确保已获取注释(有关详细信息,请参阅日常使用)。拥有这些注释后,注释将显示在 git log 命令中,如下所示

% git log

如果您想要特定版本,可以使用此结构

% git log --grep revision=XXXX

查找特定版本。commit 后面的十六进制数字是您可以用来引用此提交的哈希值。

5.6. Git 常见问题解答

本节针对用户和开发人员可能会经常遇到的问题提供了许多有针对性的答案。

我们使用常见的约定,将 FreeBSD 仓库的来源设置为“freebsd”,而不是默认的“origin”,以允许人们将其用于自己的开发并最大限度地减少对错误仓库的“糟糕”推送。

5.6.1. 用户

5.6.1.1. 如何仅使用一个仓库副本跟踪 -current 和 -stable?

问:虽然磁盘空间不是什么大问题,但只使用一个仓库副本更有效。使用 SVN 镜像,我可以从同一个仓库检出多个树。如何在 Git 中做到这一点?

答:您可以使用 Git 工作树。有很多方法可以做到这一点,但最简单的方法是使用克隆来跟踪 -current,并使用工作树来跟踪稳定版本。虽然使用“裸仓库”已被提出作为一种应对方法,但它更复杂,在这里不会记录。

首先,您需要克隆 FreeBSD 仓库,此处显示克隆到freebsd-current以减少混淆。$URL 是最适合您的任何镜像。

% git clone -o freebsd --config remote.freebsd.fetch='+refs/notes/*:refs/notes/*' $URL freebsd-current

然后,克隆完成后,您可以简单地从中创建一个工作树。

% cd freebsd-current
% git worktree add ../freebsd-stable-12 stable/12

这会将stable/12检出到名为freebsd-stable-12的目录中,该目录与freebsd-current目录处于同一级别。创建后,它的更新方式与您期望的非常类似。

% cd freebsd-current
% git checkout main
% git pull --ff-only
# changes from upstream now local and current tree updated
% cd ../freebsd-stable-12
% git merge --ff-only freebsd/stable/12
# now your stable/12 is up to date too

我建议使用--ff-only,因为它更安全,并且可以避免意外进入“合并噩梦”状态,在这种状态下,您的树中会存在额外的更改,从而迫使进行复杂的合并,而不是简单的合并。

这里有一篇很好的文章,它更详细地介绍了这一点。

5.6.2. 开发人员

5.6.2.1. 糟糕!我提交到main,而不是另一个分支。

问:我时不时地会犯错误,错误地提交到main分支。我该怎么办?

答:首先,不要惊慌。

其次,不要推送。事实上,如果你没有推送,你几乎可以修复任何问题。本节中所有答案都假设没有推送发生。

以下答案假设您提交到main,并且想要创建一个名为issue的分支。

% git branch issue                # Create the 'issue' branch
% git reset --hard freebsd/main   # Reset 'main' back to the official tip
% git checkout issue              # Back to where you were
5.6.2.2. 糟糕!我提交了一些东西到错误的分支!

问:我一直在wilma分支上进行功能开发,但错误地在“wilma”中提交了与fred分支相关的更改。我该怎么办?

答:答案类似于上一个答案,但使用 cherry picking。这假设 wilma 上只有一个提交,但会推广到更复杂的情况。它还假设它是 wilma 上的最后一个提交(因此在git cherry-pick命令中使用 wilma),但也可以将其推广。

# We're on branch wilma
% git checkout fred		# move to fred branch
% git cherry-pick wilma		# copy the misplaced commit
% git checkout wilma		# go back to wilma branch
% git reset --hard HEAD^	# move what wilma refers to back 1 commit

Git 专家会首先将 wilma 分支倒退 1 个提交,切换到 fred,然后使用git reflog查看那个被删除的 1 个提交是什么,并将其 cherry-pick 过来。

问:但是如果我想提交一些更改到main,但出于某种原因将其他更改保留在wilma中呢?

答:与上述相同技术也适用于您希望在分支的其余部分准备就绪之前将正在处理的分支的某些部分“放入”main(例如,您注意到一个无关的错误,或修复了一个偶然的错误)。您可以将这些更改 cherry-pick 到main,然后推送到父仓库。完成此操作后,清理变得非常简单:只需git rebase -i即可。Git 会注意到您已执行此操作,并自动跳过公共更改(即使您必须更改提交消息或稍微调整提交)。无需切换回 wilma 进行调整:只需重新设置即可!

问:我想从wilma分支中分离一些更改到fred分支。

答:更通用的答案与上一个相同。您将检出/创建fred分支,一次 cherry-pick 您希望从wilma中获得的更改,然后重新设置wilma以删除您 cherry-pick 的那些更改。git rebase -i main wilma将把您带入一个编辑器,并删除与您复制到fred的提交相对应的pick行。如果一切顺利,并且没有冲突,那么您就完成了。如果没有,您需要在进行时解决冲突。

执行此操作的另一种方法是检出wilma,然后创建fred分支以指向树中的同一个点。然后,您可以git rebase -i这两个分支,通过保留 pick 行选择您想要在fredwilma中进行的更改,并从编辑器中删除其余行。有些人会在开始之前创建一个名为pre-split的标签/分支,以防拆分过程中出现问题。您可以使用以下顺序撤消它

% git checkout pre-split	# Go back
% git branch -D fred		# delete the fred branch
% git checkout -B wilma		# reset the wilma branch
% git branch -d pre-split	# Pretend it didn't happen

最后一步是可选的。如果您要再次尝试拆分,则可以省略它。

问:但我按照我读到的内容进行操作,并没有看到您最后关于创建分支的建议,现在fredwilma都搞砸了。如何找到我开始之前wilma是什么样的?我不知道我移动了多少次。

答:还没有丢失。只要时间不长,提交次数也不多(几百次),您就可以弄清楚。

所以我创建了一个 wilma 分支并在其中提交了几件事,然后决定将其拆分成 fred 和 wilma。当我执行此操作时,没有发生奇怪的事情,但假设发生了。查看您所做操作的方法是使用git reflog

% git reflog
6ff9c25 (HEAD -> wilma) HEAD@{0}: rebase -i (finish): returning to refs/heads/wilma
6ff9c25 (HEAD -> wilma) HEAD@{1}: rebase -i (start): checkout main
869cbd3 HEAD@{2}: rebase -i (start): checkout wilma
a6a5094 (fred) HEAD@{3}: rebase -i (finish): returning to refs/heads/fred
a6a5094 (fred) HEAD@{4}: rebase -i (pick): Encourage contributions
1ccd109 (freebsd/main, main) HEAD@{5}: rebase -i (start): checkout main
869cbd3 HEAD@{6}: rebase -i (start): checkout fred
869cbd3 HEAD@{7}: checkout: moving from wilma to fred
869cbd3 HEAD@{8}: commit: Encourage contributions
...
%

在这里,我们可以看到我所做的更改。您可以使用它来弄清楚事情出了什么问题。我在这里只指出一些事情。第一个是 HEAD@{X} 是一个“commitish”事物,因此您可以将其用作命令的参数。虽然如果该命令向仓库提交任何内容,则 X 数字会发生变化。您也可以使用哈希值(第一列)。

接下来,'Encourage contributions' 是我在决定拆分之前对wilma进行的最后一次提交。您也可以看到当我在创建fred分支以执行此操作时,那里有相同的哈希值。我从重新设置fred开始,您可以看到“start”、“每个步骤”以及该过程的“finish”。虽然我们这里不需要它,但您可以弄清楚到底发生了什么。幸运的是,要修复这个问题,您可以按照前一个答案的步骤进行操作,但使用哈希值869cbd3,而不是pre-split。虽然这看起来有点冗长,但它很容易记住,因为您一次只做一件事。您也可以堆叠

% git checkout -B wilma 869cbd3
% git branch -D fred

然后您就可以再次尝试了。使用哈希值checkout -B结合检出和为其创建分支。-B而不是-b强制移动预先存在的分支。无论哪种方式都可以,这就是 Git 既好又坏的地方。我倾向于使用git checkout -B xxxx hash而不是检出哈希值,然后创建/移动分支的原因纯粹是为了避免关于分离头的稍微令人不安的消息

% git checkout 869cbd3
M	faq.md
Note: checking out '869cbd3'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 869cbd3 Encourage contributions
% git checkout -B wilma

这会产生相同的效果,但我必须阅读更多内容,并且断开的头并不是我喜欢的图像。

5.6.2.3. 糟糕!我执行了git pull,它创建了一个合并提交,我该怎么办?

问:我处于自动驾驶状态,并对我的开发树执行了git pull,这在main上创建了一个合并提交。我该如何恢复?

答:当您调用带有已检出开发分支的 pull 时,可能会发生这种情况。

在 pull 之后,您将检出新的合并提交。Git 支持HEAD^#语法来检查合并提交的父级

git log --oneline HEAD^1   # Look at the first parent's commits
git log --oneline HEAD^2   # Look at the second parent's commits

从这些日志中,您可以轻松地识别哪个提交是您的开发工作。然后,您只需将您的分支重置到相应的HEAD^#

git reset --hard HEAD^2

问:但我也需要修复我的main分支。我该如何做?

答:Git 在freebsd/命名空间中跟踪远程仓库分支。要修复您的main分支,只需将其指向远程的main

git branch -f main freebsd/main

Git 中的分支并没有什么神奇之处:它们只是图上的标签,通过提交自动向前移动。所以上面的操作之所以有效,是因为你只是在移动标签。由于这种操作,分支没有需要保留的元数据。

5.6.2.4. 混合和匹配分支

问:我有两个分支 workerasync,我想将它们合并成一个名为 feature 的分支,同时保留两个分支中的提交。

答:这需要用到 cherry pick。

% git checkout worker
% git checkout -b feature	# create a new branch
% git cherry-pick main..async	# bring in the changes

现在你有了名为 feature 的新分支。该分支结合了两个分支的提交。你可以用 git rebase 对其进行进一步整理。

问:我有一个名为 driver 的分支,我想将其分成 kerneluserland,以便我可以分别对它们进行演进,并在每个分支准备就绪时提交。

答:这需要一些准备工作,但 git rebase 将承担大部分工作。

% git checkout driver		# Checkout the driver
% git checkout -b kernel	# Create kernel branch
% git checkout -b userland	# Create userland branch

现在你有两个完全相同的分支。因此,是时候将提交分开了。我们首先假设 driver 中的所有提交都进入 kerneluserland 分支,但不会同时进入这两个分支。

% git rebase -i main kernel

并只包含你想要的更改(带有 'p' 或 'pick' 行),并删除你不想要的提交(这听起来很吓人,但最坏的情况是,你可以丢弃所有这些更改,从 driver 分支重新开始,因为你还没有移动它)。

% git rebase -i main userland

并对 kernel 分支执行相同的操作。

问:太棒了!我按照上面的步骤操作,却遗漏了 kernel 分支中的一个提交。如何恢复?

答:你可以使用 driver 分支查找丢失的提交的哈希值,并使用 cherry pick 将其恢复。

% git checkout kernel
% git log driver
% git cherry-pick $HASH

问:好的。我遇到了与上面相同的情况,但我的提交都混在一起了。我需要将一个提交的一部分移到一个分支,另一部分移到另一个分支。事实上,我有好几个提交是这样的。你的 rebase 方法来选择听起来很麻烦。

答:在这种情况下,你最好整理原始分支以分离出提交,然后使用上面的方法来拆分分支。

所以,假设只有一个提交,并且其树结构干净。你可以使用 git rebase 带有 edit 行,也可以使用它来处理最顶端的提交。无论哪种方式,步骤都是一样的。我们需要做的第一件事是备份一个提交,同时将未提交的更改保留在树中。

% git reset HEAD^

注意:不要,重复一遍,不要添加 --hard,因为这也会从你的树中删除更改。

现在,如果你幸运的话,需要拆分的更改完全位于文件行上。在这种情况下,你只需对每个组中的文件执行常规的 git add,然后执行 git commit。注意:当你这样做的时候,你会在执行重置操作时丢失提交信息,因此如果你需要它,你应该保存一个副本(尽管 git log $HASH 可以恢复它)。

如果你不走运,你需要将文件拆开。还有一个工具可以做到这一点,你可以一次应用一个文件。

git add -i foo/bar.c

会逐步执行差异,并提示你一次性地选择包含或排除 hunk。完成之后,git commit,你将拥有树中的剩余部分。你也可以多次运行它,甚至跨多个文件运行它(尽管我发现一次处理一个文件并使用 git rebase -i 将相关的提交折叠在一起更容易)。

5.6.3. 克隆和镜像

问:我想镜像整个 Git 仓库,怎么做?

答:如果你只想镜像,那么

% git clone --mirror $URL

就可以了。但是,如果你想将它用于除了镜像之外的用途,比如重新克隆,那么它有两个缺点。

首先,这是一个 '裸仓库',它拥有仓库数据库,但没有检出的工作树。这对于镜像来说很好,但对于日常工作来说很糟糕。可以使用 git worktree 来解决这个问题。

% git clone --mirror https://git.freebsd.org/ports.git ports.git
% cd ports.git
% git worktree add ../ports main
% git worktree add ../quarterly branches/2020Q4
% cd ../ports

但是,如果你没有将你的镜像用于进一步的本地克隆,那么它就不适合你。

第二个缺点是 Git 通常会重写上游的 refs(分支名称、标签等),以便你的本地 refs 可以独立于上游进行演进。这意味着如果你对这个仓库进行提交,除了私有项目分支之外,你会丢失更改。

问:那么我该怎么办?

答:你可以将所有上游仓库的 refs 塞入本地仓库的私有命名空间中。Git 通过 'refspec' 克隆所有内容,默认的 refspec 是

        fetch = +refs/heads/*:refs/remotes/freebsd/*

它表示只获取分支 refs。

但是,FreeBSD 仓库中还有很多其他的东西。要查看这些内容,你可以为每个 ref 命名空间添加显式的 refspec,或者你可以获取所有内容。要设置你的仓库以执行此操作

git config --add remote.freebsd.fetch '+refs/*:refs/freebsd/*'

这将把上游仓库中的所有内容放入本地仓库的 refs/freebsd/ 命名空间中。请注意,这也会获取所有未转换的 vendor 分支,以及与它们相关的 refs 数量非常多。

你需要使用完整的名称来引用这些 'refs',因为它们不在 Git 的常规命名空间中。

git log refs/freebsd/vendor/zlib/1.2.10

将查看从 1.2.10 开始的 zlib 的 vendor 分支的日志。

5.7. 与他人协作

在 FreeBSD 这样的大型项目中,良好的软件开发的关键之一是能够在将你的更改推送到树之前与他人协作。FreeBSD 项目的 Git 仓库目前不允许用户创建的分支推送到仓库中,因此如果你想与他人共享你的更改,你必须使用其他机制,比如托管的 GitLab 或 GitHub,来共享用户创建的分支中的更改。

以下说明展示了如何设置一个基于 FreeBSD main 分支的用户创建分支,并将其推送到 GitHub。

在开始之前,请确保你的本地 Git 仓库是最新的,并且设置了正确的来源 如上所示

````
% git remote -v
freebsd https://git.freebsd.org/src.git (fetch)
freebsd ssh://git@gitrepo.freebsd.org/src.git (push)
````

第一步是在 GitHub 上创建一个 FreeBSD 的 fork,遵循以下 指南。fork 的目标应该是你自己的个人 GitHub 账户(在我的例子中是 gvnn3)。

现在在你的本地系统上添加一个指向你的 fork 的远程仓库

% git remote add github git@github.com:gvnn3/freebsd-src.git
% git remote -v
github	git@github.com:gvnn3/freebsd-src.git (fetch)
github	git@github.com:gvnn3/freebsd-src.git (push)
freebsd	https://git.freebsd.org/src.git (fetch)
freebsd	ssh://git@gitrepo.freebsd.org/src.git (push)

有了它,你就可以创建分支了 如上所示

% git checkout -b gnn-pr2001-fix

在你的分支中进行你想要的任何修改。构建、测试,一旦你准备好与他人协作,就可以将你的更改推送到你托管的分支中。在推送之前,你必须设置适当的上游,因为 Git 会在你第一次尝试推送到你的 github 远程仓库时告诉你

% git push github
fatal: The current branch gnn-pr2001-fix has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream github gnn-pr2001-fix

根据 Git 的建议设置推送操作,使其能够成功

% git push --set-upstream github gnn-feature
Enumerating objects: 20486, done.
Counting objects: 100% (20486/20486), done.
Delta compression using up to 8 threads
Compressing objects: 100% (12202/12202), done.
Writing objects: 100% (20180/20180), 56.25 MiB | 13.15 MiB/s, done.
Total 20180 (delta 11316), reused 12972 (delta 7770), pack-reused 0
remote: Resolving deltas: 100% (11316/11316), completed with 247 local objects.
remote:
remote: Create a pull request for 'gnn-feature' on GitHub by visiting:
remote:      https://github.com/gvnn3/freebsd-src/pull/new/gnn-feature
remote:
To github.com:gvnn3/freebsd-src.git
 * [new branch]                gnn-feature -> gnn-feature
Branch 'gnn-feature' set up to track remote branch 'gnn-feature' from 'github'.

之后对同一分支的更改将默认情况下正确推送

% git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 314 bytes | 1024 bytes/s, done.
Total 3 (delta 1), reused 1 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:gvnn3/freebsd-src.git
   9e5243d7b659..cf6aeb8d7dda  gnn-feature -> gnn-feature

此时,你的工作现在已在你 GitHub 上的分支中,你可以与其他协作者共享链接。

5.8. 合并 GitHub 拉取请求

本节介绍如何合并提交到 GitHub 上 FreeBSD Git 镜像的 GitHub 拉取请求。虽然这目前不是提交补丁的官方方式,但有时良好的修复会以这种方式提交,最简单的方法是将它们合并到提交者的树中,然后从那里将它们推送到 FreeBSD 的树中。类似的步骤可以用来从其他仓库拉取分支并合并它们。当提交来自他人的拉取请求时,应该格外注意检查所有更改,以确保它们与描述完全一致。

在开始之前,请确保本地 Git 仓库是最新的,并且设置了正确的来源 如上所示。此外,请确保设置了以下来源

% git remote -v
freebsd https://git.freebsd.org/src.git (fetch)
freebsd ssh://git@gitrepo.freebsd.org/src.git (push)
github https://github.com/freebsd/freebsd-src (fetch)
github https://github.com/freebsd/freebsd-src (fetch)

通常情况下,拉取请求很简单:只包含一个提交的请求。在这种情况下,可以使用简化的方法,尽管前面部分的方法也适用。这里,创建一个分支,cherry pick 更改,调整提交信息,并在推送之前进行 sanity 检查。本例中使用分支 staging,但可以是任何名称。此技术适用于拉取请求中的任意数量的提交,尤其是在更改可以干净地应用到 FreeBSD 树中时。但是,当有多个提交时,尤其是在需要进行微调时,git rebase -igit cherry-pick 更好。简而言之,这些命令创建了一个分支;从拉取请求中 cherry pick 更改;测试它;调整提交信息;并将其快速向前合并回 main。PR 编号为 $PR。调整信息时,请添加 Pull Request: https://github.com/freebsd-src/pull/$PR。所有提交到 FreeBSD 仓库的拉取请求都应由至少一人审核。这不需要是提交者,但如果是这种情况,提交者应该信任其他审核者的能力来审核提交。在将拉取请求推送到仓库之前对其进行代码审核的提交者应该在提交中添加 Reviewed by: 行,因为在这种情况下,它不是隐式的。将所有在 GitHub 上审核并批准提交的人员添加到 Reviewed by: 中。与往常一样,应该注意确保更改按预期执行,并且不存在恶意代码。

此外,请检查以确保拉取请求作者名称不是匿名的。GitHub 的网页编辑界面会生成类似于以下的名称

Author:     github-user <38923459+github-user@users.noreply.github.com>

请礼貌地向作者提出更改名称和/或电子邮件的请求。应格外注意,不要引入任何样式问题或恶意代码。

% git fetch github pull/$PR/head:staging
% git rebase -i main staging	# to move the staging branch forward, adjust commit message here
<do testing here, as needed>
% git checkout main
% git pull --ff-only		# to get the latest if time has passed
% git checkout main
% git merge --ff-only staging
<test again if needed>
% git push freebsd --push-option=confirm-author

对于包含多个带有冲突的提交的复杂拉取请求,请遵循以下概述。

  1. 检出拉取请求 git checkout github/pull/XXX

  2. 创建一个分支以进行变基 git checkout -b staging

  3. 使用 git rebase -i main stagingstaging 分支变基到最新的 main

  4. 解决冲突并进行必要的测试

  5. 如上所示,将 staging 分支快进到 main

  6. 最终对更改进行完整性检查,以确保一切正常

  7. 推送到 FreeBSD 的 Git 仓库。

这也可以用于将从其他地方开发的分支合并到本地树中以进行提交。

完成拉取请求后,使用 GitHub 的 Web 界面关闭它。值得注意的是,如果你的 github 来源使用 https://,你只需要一个 GitHub 帐户来关闭拉取请求。

6. 版本控制历史记录

该项目已迁移到 git

FreeBSD 源代码仓库于 2008 年 5 月 31 日从 CVS 切换到 Subversion。第一个真正的 SVN 提交是 r179447。源代码仓库于 2020 年 12 月 23 日从 Subversion 切换到 Git。最后一个真正的 svn 提交是 r368820。第一个真正的 git 提交哈希是 5ef5f51d2bef80b0ede9b10ad5b0e9440b60518c

FreeBSD 的 doc/www 仓库于 2012 年 5 月 19 日从 CVS 切换到 Subversion。第一个真正的 SVN 提交是 r38821。文档仓库于 2020 年 12 月 8 日从 Subversion 切换到 Git。最后一个 SVN 提交是 r54737。第一个真正的 git 提交哈希是 3be01a475855e7511ad755b2defd2e0da5d58bbe

FreeBSD 的 ports 仓库于 2012 年 7 月 14 日从 CVS 切换到 Subversion。第一个真正的 SVN 提交是 r300894。ports 仓库于 2021 年 4 月 6 日从 Subversion 切换到 Git。最后一个 SVN 提交是 r569609。第一个真正的 git 提交哈希是 ed8d3eda309dd863fb66e04bccaa513eee255cbf

7. 设置、约定和传统

作为一名新开发者,你需要做一些事情。第一组步骤仅针对提交者。对于非提交者,这些步骤必须由导师完成。

7.1. 针对新提交者

获得 FreeBSD 仓库提交权限的人必须遵循这些步骤。

  • 在提交每个更改之前,请获得导师的批准!

  • 所有 src 提交都首先进入 FreeBSD-CURRENT,然后再合并到 FreeBSD-STABLE。FreeBSD-STABLE 分支必须保持与该分支早期版本的 ABI 和 API 兼容性。不要合并破坏这种兼容性的更改。

针对新提交者的步骤

  1. 添加作者实体

    doc/shared/authors.adoc - 添加作者实体。后续步骤取决于此实体,如果缺少此步骤,doc/ 构建将失败。这是一个比较简单的任务,但仍然是测试版本控制技能的良好测试。

  2. 更新开发者和贡献者列表

    doc/shared/contrib-committers.adoc - 添加条目,该条目将出现在 贡献者列表 的“开发者”部分。条目按姓氏排序。

    doc/shared/contrib-additional.adoc - 删除该条目。条目按名字排序。

  3. 添加新闻项

    doc/website/data/en/news/news.toml - 添加条目。查找其他宣布新提交者的条目,并遵循格式。使用提交位批准电子邮件中的日期。

  4. 添加 PGP 密钥

    Dag-Erling Smørgrav <des@FreeBSD.org> 编写了一个 shell 脚本 (doc/documentation/tools/addkey.sh) 以简化此操作。有关更多信息,请参阅 README 文件。

    使用 doc/documentation/tools/checkkey.sh 验证密钥是否符合最低最佳实践标准。

    添加并检查密钥后,将两个更新后的文件添加到源代码控制,然后提交它们。此文件中的条目按姓氏排序。

    在仓库中拥有当前的 PGP/GnuPG 密钥非常重要。该密钥可能需要用于对提交者进行正面识别。例如,FreeBSD Administrators <admins@FreeBSD.org> 可能需要它来恢复帐户。可以从 https://docs.freebsd.ac.cn/pgpkeys/pgpkeys.txt 下载 FreeBSD.org 用户的完整密钥环。

  5. 更新导师和受训者信息

    src/share/misc/committers-<repository>.dot - 在当前提交者部分添加一个条目,其中 repositorydocportssrc,具体取决于授予的提交权限。

    在底部部分中,为每个额外的导师/受训者关系添加一个条目。

  6. 生成 Kerberos 密码

    请参阅 FreeBSD 集群的 Kerberos 和 LDAP Web 密码,以生成或设置 Kerberos 帐户,用于与其他 FreeBSD 服务(例如 错误跟踪数据库)一起使用(你将在该步骤中获得一个错误跟踪帐户)。

  7. 可选:启用 Wiki 帐户

    FreeBSD Wiki 帐户 - Wiki 帐户允许共享项目和想法。还没有帐户的人可以按照 Wiki/About 页面 上的说明获取一个帐户。如果你需要有关 Wiki 帐户的帮助,请联系 wiki-admin@FreeBSD.org

  8. 可选:更新 Wiki 信息

    Wiki 信息 - 获得对 Wiki 的访问权限后,有些人会向 How We Got HereIRC 昵称FreeBSD 的狗狗FreeBSD 的猫咪 页面添加条目。

  9. 可选:使用个人信息更新 Ports

    ports/astro/xearth/files/freebsd.committers.markerssrc/usr.bin/calendar/calendars/calendar.freebsd - 有些人会在这些文件中添加自己的条目,以显示他们的位置或生日日期。

  10. 可选:防止重复邮件

    订阅了 doc 仓库所有分支的提交消息ports 仓库所有分支的提交消息src 仓库所有分支的提交消息 的人可能希望取消订阅,以避免收到重复的提交消息和后续回复。

7.2. 针对所有人

  1. 向其他开发者介绍你自己,否则没有人会知道你是谁或你在做什么。介绍不需要是完整的传记,只需写一两段关于你是谁、你计划作为 FreeBSD 开发者做什么以及你的导师是谁。将此电子邮件发送到 FreeBSD 开发者邮件列表,你就可以开始了!

  2. 登录 freefall.FreeBSD.org 并创建一个包含你想将邮件转发到的电子邮件地址的 /var/forward/user(其中 user 是你的用户名)文件,该地址将被转发到 yourusername@FreeBSD.org。这包括所有提交消息以及发送到 FreeBSD 提交者邮件列表和 FreeBSD 开发者邮件列表的任何其他邮件。如果 freefall 上的真正大型邮箱已永久驻留,并且需要释放空间,则可能会在没有警告的情况下被截断,因此请将它转发或保存到其他地方。

    如果你的电子邮件系统使用具有严格规则的 SPF,你应该从 SPF 检查中排除 mx2.FreeBSD.org

    由于处理 SPAM 邮件对执行邮件列表处理的中央邮件服务器造成了严重的负载,因此前端服务器会执行一些基本检查,并会根据这些检查删除一些消息。目前,仅实施了对连接主机的正确 DNS 信息的检查,但这可能会改变。有些人将这些检查归咎于反弹有效电子邮件。要为你的电子邮件关闭这些检查,请在 freefall.FreeBSD.org 上创建一个名为 ~/.spam_lover 的文件。

    那些是开发者但不是提交者的人将不会订阅提交者或开发者邮件列表。订阅是从访问权限中得出的。

7.2.1. SMTP 访问设置

对于愿意通过 FreeBSD.org 基础设施发送电子邮件的人,请遵循以下说明

  1. 将你的邮件客户端指向 smtp.FreeBSD.org:587

  2. 启用 STARTTLS。

  3. 确保你的 From: 地址设置为 yourusername@FreeBSD.org

  4. 对于身份验证,你可以使用你的 FreeBSD Kerberos 用户名和密码(请参阅 FreeBSD 集群的 Kerberos 和 LDAP Web 密码)。yourusername/mail 主体是首选的,因为它仅对身份验证到邮件资源有效。

    输入用户名时,不要包含 @FreeBSD.org

    其他注意事项
    • 只接受来自 yourusername@FreeBSD.org 的邮件。如果你以一个用户身份进行身份验证,则不允许你以其他用户身份发送邮件。

    • 将使用 SASL 用户名附加一个标题:(Authenticated sender: username)。

    • 主机已实施各种速率限制,以减少暴力攻击。

7.2.1.1. 使用本地 MTA 将电子邮件转发到 FreeBSD.org SMTP 服务

也可以使用本地 MTA 将本地发送的电子邮件转发到 FreeBSD.org SMTP 服务器。

示例 1. 使用 Postfix

要告诉本地 Postfix 实例将来自 yourusername@FreeBSD.org 的所有内容转发到 FreeBSD.org 服务器,请将以下内容添加到你的 main.cf

sender_dependent_relayhost_maps = hash:/usr/local/etc/postfix/relayhost_maps
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/usr/local/etc/postfix/sasl_passwd
smtp_use_tls = yes

创建 /usr/local/etc/postfix/relayhost_maps,内容如下

yourusername@FreeBSD.org  [smtp.freebsd.org]:587

创建 /usr/local/etc/postfix/sasl_passwd,内容如下

[smtp.freebsd.org]:587          yourusername:yourpassword

如果邮件服务器被其他人使用,您可能希望阻止他们从您的地址发送电子邮件。为此,请将以下内容添加到您的 main.cf

smtpd_sender_login_maps = hash:/usr/local/etc/postfix/sender_login_maps
smtpd_sender_restrictions = reject_known_sender_login_mismatch

创建 /usr/local/etc/postfix/sender_login_maps 文件,内容如下

yourusername@FreeBSD.org yourlocalusername

其中 yourlocalusername 是用于连接到 Postfix 本地实例的 SASL 用户名。

示例 2. 使用 OpenSMTPD

要告诉 OpenSMTPD 本地实例将来自 yourusername@FreeBSD.org 的所有内容转发到 FreeBSD.org 服务器,请将以下内容添加到您的 smtpd.conf

action "freebsd" relay host smtp+tls://freebsd@smtp.freebsd.org:587 auth <secrets>
match from any auth yourlocalusername mail-from "_yourusername_@freebsd.org" for any action "freebsd"

其中 yourlocalusername 是用于连接到 OpenSMTPD 本地实例的 SASL 用户名。

创建 /usr/local/etc/mail/secrets 文件,内容如下

freebsd	yourusername:yourpassword
示例 3. 使用 Exim

要指示 Exim 本地实例将来自 example@FreeBSD.org 的所有邮件转发到 FreeBSD.org 服务器,请将以下内容添加到 Exim 配置

Routers section: (at the top of the list):
freebsd_send:
   driver = manualroute
   domains = !+local_domains
   transport = freebsd_smtp
   route_data = ${lookup {${lc:$sender_address}} lsearch {/usr/local/etc/exim/freebsd_send}}

Transport Section:
freebsd_smtp:
        driver = smtp
  tls_certificate=<local certificate>
  tls_privatekey=<local certificate private key>
  tls_require_ciphers = EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+AESGCM:EECDH:EDH+AESGCM:EDH+aRSA:HIGH:!MEDIUM:!LOW:!aNULL:!eNULL:!LOW:!RC4:!MD5:!EXP:!PSK:!SRP:!DSS
  dkim_domain = <local DKIM domain>
  dkim_selector = <local DKIM selector>
  dkim_private_key= <local DKIM private key>
  dnssec_request_domains = *
  hosts_require_auth = smtp.freebsd.org

Authenticators:
freebsd_plain:
  driver = plaintext
  public_name = PLAIN
  client_send = ^example/mail^examplePassword
  client_condition = ${if eq{$host}{smtp.freebsd.org}}

创建 /usr/local/etc/exim/freebsd_send 文件,内容如下

example@freebsd.org:smtp.freebsd.org::587

7.3. 导师

所有新开发人员在最初的几个月都会被分配一名导师。导师负责教授受训者项目的规则和惯例,并指导他们在开发者社区中的第一步。导师还对受训者在此初始阶段的行为负有个人责任。

对于提交者:在获得导师批准之前,请勿提交任何内容。在提交消息中使用 Approved by: 行记录批准。

当导师认为受训者已经掌握了技巧并可以独立提交时,导师会在 mentors 中提交一个更改来宣布此事。该文件位于每个存储库的 admin 孤儿分支中。有关如何访问这些分支的详细信息,请参阅 admin

8. 提交前审查

代码审查是提高软件质量的一种方式。以下准则适用于提交到 src 存储库的 main(-CURRENT)分支。其他分支以及 portsdocs 树有自己的审查策略,但这些准则通常适用于需要审查的提交

  • 所有非平凡的更改在提交到存储库之前都应进行审查。

  • 审查可以通过电子邮件、Bugzilla、Phabricator 或其他机制进行。在可能的情况下,审查应公开进行。

  • 负责代码更改的开发人员也负责进行所有必要的审查相关更改。

  • 代码审查可以是一个迭代过程,该过程将一直持续到补丁准备就绪可以提交为止。具体来说,一旦补丁被发送出去进行审查,它应该在提交之前收到明确的“看起来不错”的确认。只要明确,它可以采用对审查方法有意义的任何形式。

  • 超时不能替代审查。

有时代码审查会比您希望的持续时间更长,特别是对于大型功能而言。以下是一些加速补丁审查时间的方法

  • 审查其他人的补丁。如果您提供帮助,每个人都将更愿意为您做同样的事情;善意是我们的货币。

  • Ping 补丁。如果紧急,请说明为什么对您来说让此补丁落地很重要,并每隔几天 ping 一次。如果它不紧急,常见的礼貌 ping 频率是一周。请记住,您正在向其他专业开发人员索取宝贵的时间。

  • 在邮件列表、IRC 等地方寻求帮助。其他人可能能够直接帮助您,或者推荐一位审阅者。

  • 将您的补丁分成多个较小的补丁,这些补丁相互建立。您的补丁越小,有人快速查看它的可能性就越大。

    在进行重大更改时,最好从一开始就牢记这一点,因为事后将重大更改分解成较小的更改通常很困难。

开发人员应作为审阅者和被审阅者参与代码审查。如果有人好心地审查了您的代码,您也应该为其他人做同样的事情。请注意,虽然任何人都可以审查和提供补丁反馈,但只有合适的主题专家才能批准更改。这通常是定期处理相关代码的提交者。

在某些情况下,可能没有主题专家可用。在这些情况下,经验丰富的开发人员的审查与适当的测试相结合就足够了。

9. 提交日志消息

本节包含一些关于如何格式化提交日志的建议和传统。

9.1. 为什么提交消息很重要?

当您在 Git、Subversion 或其他版本控制系统 (VCS) 中提交更改时,系统会提示您编写一些描述提交的文本——提交消息。此提交消息有多重要?您是否应该花一些精力编写它?如果您只写 fixed a bug,真的重要吗?

大多数项目都有多个开发人员,并持续一段时间。提交消息是在当下和将来与其他开发人员进行沟通的一种非常重要的方式。

FreeBSD 有数百名活跃开发人员,并且有数十万个提交,跨越了数十年的历史。在这么长的时间里,开发者社区已经了解了高质量提交消息的价值;有时这些都是惨痛的教训。

提交消息至少有三个目的

  • 与其他开发人员进行沟通

    FreeBSD 提交会向各种邮件列表生成电子邮件。这些包括提交消息以及补丁本身的副本。提交消息也可以通过 git log 等命令查看。这些用于让其他开发人员了解正在进行的更改;该开发人员可能想要测试更改,可能对该主题感兴趣并希望详细审查,或者他们自己的项目正在进行中,这些项目可能需要进行交互。

  • 使更改可发现

    在一个大型项目中,随着时间的推移,在调查问题或行为变化时,可能很难找到感兴趣的更改。冗长详细的提交消息允许搜索可能相关的更改。例如,git log --since 1year --grep 'USB timeout'

  • 提供历史文档

    提交消息用于为未来的开发人员记录更改,也许是几年或几十年后。这个未来的开发人员甚至可能是您,最初的作者。今天看起来很明显的更改可能在将来变得不那么明显了。

git blame 命令将源文件的每一行都用它带入的更改(哈希值和主题行)进行注释。

在确定了重要性之后,以下是优质 FreeBSD 提交消息的元素

9.2. 从主题行开始

提交消息应以单行主题开头,该主题简要概括更改。主题本身应使读者能够快速确定更改是否与他们相关。

9.3. 保持主题行简短

主题行应尽可能短,同时保留必要的信息。这是为了使浏览 Git 日志更加高效,以便 git log --oneline 能够在一行 80 列上显示短哈希值和主题。一个好的经验法则是保持在 63 个字符以内,如果可能,尽量保持在 50 个字符或更少。

9.4. 如果适用,在主题行前面加上组件

如果更改与特定组件相关,则主题行可以在前面加上该组件名称和冒号 (:)。

foo: Add -k option to keep temporary data

在上面建议的 63 个字符限制中包含前缀,以便 git log --oneline 避免换行。

9.5. 将主题的首字母大写

将主题本身的首字母大写。前缀(如果有)除非必要,否则不应大写(例如,USB: 大写)。

9.6. 不要在主题行末尾使用标点符号

不要在末尾使用句点或其他标点符号。在这方面,主题行就像报纸标题。

9.7. 使用空行分隔主题和主体

使用空行分隔主体和主题。

一些微不足道的提交不需要主体,并且只包含主题。

ls: Fix typo in usage text

9.8. 将消息限制为 72 列

git loggit format-patch 会将提交消息缩进四个空格。在 72 列处换行会在右边提供匹配的边距。将消息限制为 72 个字符还可以使格式化补丁中的提交消息保持在 RFC 2822 建议的 78 个字符的电子邮件行长度限制以下。此限制非常适合各种可能呈现提交消息的工具;对于更长的行长度,行换行可能不一致。

9.9. 使用现在时,祈使语气

这有利于简短的主题行并提供一致性,包括自动生成的提交消息(例如,由 git revert 生成)。这在阅读提交主题列表时很重要。将主题视为完成句子“应用后,此更改将……”。

foo: Implement the -k (keep) option
foo: Implemented the -k option
This change implements the -k option in foo
-k option added

9.10. 重点关注做什么和为什么,而不是怎么做

解释更改完成了什么以及为什么要进行更改,而不是怎么做。

不要假设读者熟悉这个问题。解释更改的背景和动机。如果手边有基准数据,请将其包含在内。

如果更改存在限制或不完整之处,请在提交消息中进行描述。

9.11. 考虑是否将提交信息的部分内容作为代码注释

有时在编写提交信息时,您可能会发现自己写了一两句话来解释更改的某些棘手或令人困惑的方面。 发生这种情况时,请考虑将该解释作为代码本身的注释是否有价值。

9.12. 为未来的自己编写提交信息

在为更改编写提交信息时,您会记住所有上下文 - 是什么促使了更改,考虑并拒绝的替代方法,更改的局限性等等。 想象一下自己在一两年后重新审视该更改,并以提供必要上下文的方式编写提交信息。

9.13. 提交信息应独立存在

您可以包含对邮件列表帖子的引用、基准结果网站或代码审查链接。 但是,提交信息应包含所有相关信息,以防这些引用在将来不再可用。

同样,提交可能引用之前的提交,例如在修复错误或还原的情况下。 除了提交标识符(修订版或哈希值)之外,还包括所引用提交的主题行(或其他合适的简短引用)。 随着每次 VCS 迁移(从 CVS 到 Subversion 再到 Git),来自先前系统的修订版标识符可能难以跟踪。

除了在每次提交时都包含信息丰富的消息之外,可能还需要一些其他信息。

此信息由包含关键字或短语、冒号、用于格式化的制表符,以及其他信息的 一行或多行组成。

关键字或短语是

PR

受此提交影响(通常是通过关闭)的问题报告(如果有)。 一行中可以指定多个 PR,用逗号或空格分隔。

报告人

报告问题的人员的姓名和电子邮件地址; 对于开发人员,只需使用 FreeBSD 集群上的用户名即可。 通常在没有 PR 的情况下使用,例如如果问题是在邮件列表上报告的。

提交人
(已弃用)

此功能已在 git 中弃用; 提交的补丁应使用git commit --author 设置作者,并使用完整名称和有效的电子邮件地址。

审核人

审查更改的人员或人员的姓名和电子邮件地址; 对于开发人员,只需使用 FreeBSD 集群上的用户名即可。 如果补丁已提交到邮件列表以供审查,并且审查结果良好,则只需包含列表名称。 如果审阅者不是项目成员,请提供姓名、电子邮件,以及如果端口是外部角色,例如维护者。

由开发人员审查

Reviewed by: username

由不是开发人员的端口维护者审查

Reviewed by: Full Name <valid@email> (maintainer)

测试人

测试更改的人员或人员的姓名和电子邮件地址; 对于开发人员,只需使用 FreeBSD 集群上的用户名即可。

与...讨论

通过提供有意义的反馈而为补丁做出贡献的人员或人员的姓名和电子邮件地址; 对于开发人员,只需使用 FreeBSD 集群上的用户名即可。 通常用于表彰那些没有明确审查、测试或批准更改的人员,但仍然参与了围绕更改的讨论,从而导致改进,并更好地理解其对 FreeBSD 项目的影响。

批准人

批准更改的人员或人员的姓名和电子邮件地址; 对于开发人员,只需使用 FreeBSD 集群上的用户名即可。

在以下几种情况下,批准是惯例

  • 新提交者在指导下

  • 提交到 LOCKS 文件(src)覆盖的树区域

  • 在发布周期期间

  • 提交到您没有提交位的存储库(例如,src 提交者提交到 docs)

  • 提交到其他人维护的端口

在指导下,在提交之前获得导师的批准。 在此字段中输入导师的用户名,并注意他们是导师

Approved by: username-of-mentor (mentor)

如果团队批准了这些提交,则包含团队名称,然后在括号中包含批准者的用户名。 例如

Approved by: re (username)

从...获取

获得代码的项目名称(如果有)。 不要将此行用于个人姓名。

修复

由此更改修复的提交的 Git 短哈希值和标题行,如git log -n 1 --pretty=format:'%h ("%s")' GIT-COMMIT-HASH 返回的结果。

MFC 后

要收到 MFC 提醒电子邮件,以在稍后日期进行 MFC,请指定计划 MFC 的天数、周数或月数。

MFC 到

如果提交应合并到稳定分支的子集,请指定分支名称。

MFH

如果提交要合并到端口季度分支名称,请指定季度分支。 例如 2021Q2

发行说明

如果更改是候选加入下一个分支版本的发行说明,则设置为 yes

安全

如果更改与安全漏洞或安全漏洞有关,请包含一个或多个引用或问题说明。 如果可能,请包含 VuXML URL 或 CVE ID。

活动

进行此提交的事件的说明。 如果这是一个经常发生的事件,请在其中添加年份甚至月份。 例如,这可能是 FooBSDcon 2019。 此行背后的理念是认可会议、聚会和其他类型的聚会,并表明这些聚会很有用。 请不要为此使用 由...赞助: 行,因为该行用于赞助某些功能或在这些功能上工作的组织。

由...赞助

此更改的赞助组织(如果有)。 用逗号分隔多个组织。 如果只有一部分工作受到赞助,或者不同数量的赞助提供给了不同的作者,请在每个赞助者名称后以括号的形式给出适当的认可。 例如,Example.com (alice, 代码重构),Wormulon (bob),Momcorp (cindy) 显示 Alice 由 Example.com 赞助进行代码重构,而 Wormulon 赞助了 Bob 的工作,Momcorp 赞助了 Cindy 的工作。 其他作者要么没有受到赞助,要么选择不列出赞助信息。

拉取请求

此更改作为拉取请求或合并请求提交到 FreeBSD 的一个公共只读 Git 存储库。 它应包含指向拉取请求的完整 URL,因为这些拉取请求通常充当代码的代码审查。 例如:https://github.com/freebsd/freebsd-src/pull/745

共同作者

提交的额外作者的姓名和电子邮件地址。 GitHub 在 https://githubdocs.cn/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors 中详细介绍了共同作者尾部信息。

签署人

ID 证明符合 https://developercertificate.org/

差异修订

Phabricator 审查的完整 URL。 此行必须是最后一行。 例如:https://reviews.freebsd.org/D1708

示例 4. 基于 PR 的提交的提交日志

该提交基于来自 John Smith 提交的 PR 的补丁。 提交消息的 "PR" 字段已填充。

...

PR:		12345

提交者使用 git commit --author "John Smith <John.Smith@example.com>" 设置补丁的作者。

示例 5. 需要审查的提交的提交日志

虚拟内存系统正在更改。 在将补丁发布到相应的邮件列表(在本例中为 freebsd-arch)后,更改已获批准。

...

Reviewed by:	-arch
示例 6. 需要批准的提交的提交日志

提交一个端口,在与列出的维护者一起工作后,他们表示可以继续提交。

...

Approved by:	abc (maintainer)

其中 abc 是批准人帐户的名称。

示例 7. 从 OpenBSD 引入代码的提交的提交日志

提交一些基于 OpenBSD 项目中完成的工作的代码。

...

Obtained from:	OpenBSD
示例 8. 对 FreeBSD-CURRENT 的更改的提交日志,计划在稍后日期进行到 FreeBSD-STABLE 的提交。

提交一些代码,这些代码将在两周后从 FreeBSD-CURRENT 合并到 FreeBSD-STABLE 分支。

...

MFC after:	2 weeks

其中 2 是计划 MFC 后的天数、周数或月数。 选项可以是 daydaysweekweeksmonthmonths

通常需要将这些组合起来。

考虑一个用户提交了一个 PR,其中包含来自 NetBSD 项目的代码的情况。 开发人员查看了 PR,发现它不是他们通常工作的树区域,因此他们让 arch 邮件列表审查了更改。 由于更改很复杂,开发人员选择在一个月后进行 MFC,以便进行充分的测试。

要包含在提交中的额外信息如下所示

示例 9. 示例组合提交日志
PR:		54321
Reviewed by:	-arch
Obtained from:	NetBSD
MFC after:	1 month
Relnotes:	yes

10. 新文件的首选许可证

FreeBSD 项目的完整许可证策略可以在 https://freebsd.ac.cn/internal/software-license 中找到。 本节的其余部分旨在帮助您入门。 作为一项规则,如有疑问,请咨询。 给出建议比修复源代码树要容易得多。

FreeBSD 项目建议并使用以下文本作为首选许可方案

/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) [year] [your name]
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * [id for your version control system, if any]
 */

FreeBSD 项目强烈反对在新代码中使用所谓的 "广告条款"。 由于 FreeBSD 项目的贡献者众多,因此对于许多商业供应商而言,遵守此条款变得很困难。 如果您在树中拥有带有广告条款的代码,请考虑将其删除。 事实上,请考虑对您的代码使用上述许可证。

FreeBSD 项目不鼓励完全使用新的许可证和标准许可证的变体。 新许可证需要获得 core@FreeBSD.org 的批准才能驻留在 src 存储库中。 树中使用的许可证种类越多,这会导致那些希望利用此代码的人遇到更多问题,通常是由于措辞不当的许可证造成的意外后果。

项目策略规定,在某些非 BSD 许可证下的代码必须仅放置在存储库的特定部分,在某些情况下,编译必须有条件地进行,甚至默认情况下禁用。 例如,GENERIC 内核必须仅在与 BSD 许可证相同或实质上类似的许可证下编译。 GPL、APSL、CDDL 等许可的软件不得编译到 GENERIC 中。

请提醒开发人员,在开源中,将 "开源" 做对与将 "源代码" 做对一样重要,因为对知识产权的处理不当会造成严重后果。 任何问题或疑虑应立即提请核心团队注意。

11. 跟踪授予 FreeBSD 项目的许可证

存储库中存在各种软件或数据,FreeBSD 项目已获得使用这些软件或数据的特殊许可。 一个例子是 Terminus 字体,用于 vt(4)。 在这里,作者 Dimitar Zhekov 允许我们使用 "Terminus BSD Console" 字体,使用 2 条款 BSD 许可证,而不是他通常使用的常规 Open Font License。

显然,记录所有此类许可授权是明智的。为此,core@FreeBSD.org 决定保留一份档案。 每当 FreeBSD 项目获得特殊许可时,都需要通知 core@FreeBSD.org。 任何参与安排此类许可授权的开发者,请将详细信息发送至 core@FreeBSD.org,包括

  • 授予特殊许可的个人或组织的联系方式。

  • 仓库中受许可授权涵盖的文件、目录等,包括提交任何特殊许可材料的修订号。

  • 许可生效的日期。 除非另有约定,否则该日期将为相关软件作者签发许可证的日期。

  • 许可文本。

  • 有关专门适用于 FreeBSD 使用许可材料的任何限制、限制或例外情况的说明。

  • 任何其他相关信息。

一旦 core@FreeBSD.org 确认已收集所有必要的信息并且信息准确无误,秘书将发送一份包含许可详细信息的 PGP 签名确认收据。 此收据将被永久存档,并作为我们对许可授权的永久记录。

许可证档案应仅包含许可证授权的详细信息;这里不适合进行有关许可证或其他主题的任何讨论。 您可以通过向 core@FreeBSD.org 请求访问许可证档案中的数据。

12. 树中的 SPDX 标签

该项目在我们的源代码库中使用 SPDX 标签。 目前,这些标签旨在帮助自动化工具机械地重建许可证要求。 树中的所有 SPDX-License-Identifier 标签均应被视为信息性标签。 FreeBSD 源代码树中包含这些标签的所有文件也都包含一份许可证,该许可证管理着对该文件的用途。 如果出现差异,则以逐字许可证为准。 该项目尝试遵循 SPDX 规范,版本 2.2。 如何标记源文件和有效的代数表达式可在 附录 IV附录 V 中找到。 该项目从 SPDX 的有效 简短许可证标识符 列表中提取标识符。 该项目仅使用 SPDX-License-Identifier 标签。

截至 2021 年 3 月,树中大约有 25,000 个文件(共 90,000 个文件)已标记。

13. 开发者关系

当直接处理您自己的代码或已明确确定为您的责任的代码时,可能不需要在提交前与其他提交者核实。 当在系统中明确被遗弃的某个区域(对于我们来说,的确有一些这样的区域,我们感到羞愧)处理错误时,也是如此。 当修改系统中正式或非正式维护的部分时,请考虑请求审查,就像开发者成为提交者之前会做的那样。 对于端口,请联系 Makefile 中列出的 MAINTAINER

要确定树的某个区域是否已维护,请检查树根目录下的 MAINTAINERS 文件。 如果没有列出任何人,请扫描修订历史记录,查看过去谁提交了更改。 要列出过去 2 年中特定文件的提交作者姓名和电子邮件地址以及每个作者提交的次数(按提交次数降序排列),请使用

% git -C /path/to/repo shortlog -sne --since="2 years" -- relative/path/to/file

如果查询没有得到回复或提交者以其他方式表明对受影响区域不感兴趣,请继续进行提交。

避免向维护者发送私人邮件。 其他人可能对对话感兴趣,而不仅仅是最终的输出。

如果有任何疑问,无论出于任何原因,请在提交之前进行审查。 最好是在提交之前进行审查,而不是在提交之后进行审查。 如果提交导致争议爆发,最好考虑撤回更改,直到问题解决为止。 请记住,使用版本控制系统,我们始终可以将其更改回。

不要怀疑他人的意图。 如果他们对某个问题的解决方案有不同的看法,甚至对问题本身有不同的看法,这可能不是因为他们愚蠢,也不是因为他们的出身有问题,也不是因为他们试图破坏辛苦的工作、个人形象或 FreeBSD,而是因为他们对世界有不同的看法。 不同很好。

诚实地表达不同意见。 从其优点出发来论证你的立场,诚实地说明它可能存在的任何缺陷,并以开放的心态来了解他们的解决方案,甚至了解他们对问题的看法。

接受修正。 我们都是会犯错的。 当你犯错时,道歉并继续生活。 不要自责,当然也不要因为自己的错误而责怪他人。 不要浪费时间去尴尬或指责,只需解决问题并继续前进。

寻求帮助。 寻求(并提供)同行审查。 开源软件应该在应用于它的眼球数量方面胜过其他软件,但如果没有人审查代码,这一点就无法实现。

14. 有疑问时…​

当对某些事情感到不确定时,无论是技术问题还是项目约定,请务必询问。 如果你保持沉默,你就永远无法取得进展。

如果与技术问题相关,请在公共邮件列表上提问。 避免向知道答案的人发送电子邮件。 这样,每个人都将能够从问题和答案中学习。

对于项目特定问题或管理问题,请按以下顺序询问

  • 您的导师或前任导师。

  • IRC、电子邮件等上的经验丰富的提交者。

  • 任何戴着“帽子”的团队,因为他们可以给你一个明确的答案。

  • 如果仍然不确定,请在 FreeBSD 开发者邮件列表上提问。

在您的问题得到解答后,如果没有人将您指向解释了您问题的答案的文档,请记录下来,因为其他人也会有相同的问题。

15. Bugzilla

FreeBSD 项目利用 Bugzilla 来跟踪错误和更改请求。 如果您提交了在 PR 数据库中找到的修复或建议,请务必关闭 PR。 如果你花时间关闭与你的提交相关的任何其他 PR,这也将被认为是件好事。

拥有非 FreeBSD.org Bugzilla 帐户的提交者可以通过以下步骤将旧帐户与 FreeBSD.org 帐户合并

  1. 使用您的旧帐户登录。

  2. 打开新的错误。 选择 Services 作为产品,选择 Bug Tracker 作为组件。 在错误描述中列出您希望合并的帐户。

  3. 使用 FreeBSD.org 帐户登录,并对新打开的错误发布评论以确认所有权。 有关如何为您的 FreeBSD.org 帐户生成或设置密码的更多详细信息,请参见 FreeBSD 集群的 Kerberos 和 LDAP 网络密码

  4. 如果要合并的帐户超过两个,请从每个帐户发布评论。

您可以在以下位置了解更多关于 Bugzilla 的信息

16. Phabricator

FreeBSD 项目利用 Phabricator 来请求代码审查。 有关详细信息,请参见 Phabricator Wiki 页面

拥有非 FreeBSD.org Phabricator 帐户的提交者可以通过以下步骤将旧帐户重命名为 FreeBSD.org 帐户

  1. 将您的 Phabricator 帐户电子邮件更改为您的 FreeBSD.org 电子邮件。

  2. 使用您的 FreeBSD.org 帐户在我们的错误跟踪器上打开新的错误,有关更多信息,请参见 Bugzilla。 选择 Services 作为产品,选择 Code Review 作为组件。 在错误描述中请求重命名您的 Phabricator 帐户,并提供指向您的 Phabricator 用户的链接。 例如,https://reviews.freebsd.org/p/bob_example.com/

Phabricator 帐户无法合并,请勿打开新帐户。

17. 谁是谁

除了仓库管理员之外,还有其他 FreeBSD 项目成员和团队,您可能会在担任提交者的角色中认识他们。 简而言之,这些成员并非全部,但可以概括为

文档工程团队 <doceng@FreeBSD.org>

doceng 是负责文档构建基础设施、批准新的文档提交者以及确保 FreeBSD 网站和 FTP 站点上的文档与 Subversion 树保持同步的团队。 它不是一个冲突解决机构。 大多数与文档相关的讨论都发生在 FreeBSD 文档项目邮件列表 上。 有关 doceng 团队的更多详细信息,请参见其 章程。 有兴趣为文档做出贡献的提交者应熟悉 文档项目入门

Konstantin Belousov <kib@FreeBSD.org>,Dave Cottlehuber <dch@FreeBSD.org>,Marc Fonvieille <blackend@FreeBSD.org>,John Hixson <jhixson@FreeBSD.org>,Xin Li <delphij@FreeBSD.org>,Ed Maste <emaste@FreeBSD.org>,Mahdi Mokhtari <mmokhi@FreeBSD.org>,Colin Percival <cperciva@FreeBSD.org>,Doug Rabson <dfr@FreeBSD.org>,Muhammad Moinur Rahman <bofh@FreeBSD.org>

以下是发布工程团队 <re@FreeBSD.org>的成员。该团队负责设定发布截止日期并控制发布流程。在代码冻结期间,发布工程师对即将发布状态的任何分支的系统的所有更改拥有最终决定权。如果您想将某些内容从 FreeBSD-CURRENT 合并到 FreeBSD-STABLE(无论在任何给定时间这些值可能是什么),这些都是您需要与之交谈的人。

Gordon Tetlow <gordon@FreeBSD.org>

Gordon TetlowFreeBSD 安全主管,并监管安全主管团队 <security-officer@FreeBSD.org>

FreeBSD 提交者邮件列表

{dev-src-all}、{dev-ports-all} 和 {dev-doc-all} 是版本控制系统用来向其发送提交消息的邮件列表。切勿直接向这些列表发送电子邮件。只有当回复简短且与提交内容直接相关时,才回复此列表。

FreeBSD 开发人员邮件列表

所有提交者都订阅了 -developers。创建此列表是为了成为提交者“社区”问题的论坛。例如,核心投票、公告等。

FreeBSD 开发人员邮件列表专供 FreeBSD 提交者使用。要开发 FreeBSD,提交者必须能够公开讨论将在公开宣布之前解决的问题。正在进行的工作的坦率讨论不适合公开发布,可能会损害 FreeBSD。

所有 FreeBSD 提交者都应在未经所有作者允许的情况下,不得发布或转发来自 FreeBSD 开发人员邮件列表的消息。违反者将被从 FreeBSD 开发人员邮件列表中移除,导致其提交权限被暂停。重复或公然违反可能会导致永久撤销提交权限。

此列表打算用作代码审查或任何技术讨论的地方。事实上,将它用作这种用途会损害 FreeBSD 项目,因为它给人们一种封闭列表的感觉,在这个列表中,影响所有使用 FreeBSD 社区的普遍决定是在未经“公开”的情况下做出的。最后但并非最不重要的一点是,绝不、绝不、绝不向 FreeBSD 开发人员邮件列表发送电子邮件,并抄送/密送:另一个 FreeBSD 列表。永远不要、绝不向另一个 FreeBSD 邮件列表发送电子邮件,并抄送/密送:FreeBSD 开发人员邮件列表。这样做会极大地降低此列表的好处。

18. SSH 快速入门指南

  1. 如果您不希望每次使用 ssh(1) 时都输入密码,并且使用密钥进行身份验证,ssh-agent(1) 可以为您提供便利。如果您想使用 ssh-agent(1),请确保在运行其他应用程序之前运行它。例如,X 用户通常从其 .xsession.xinitrc 中执行此操作。有关详细信息,请参阅 ssh-agent(1)

  2. 使用 ssh-keygen(1) 生成密钥对。密钥对将最终位于您的 $HOME/.ssh/ 目录中。

    仅支持 ECDSA、Ed25519 或 RSA 密钥。

  3. 将您的公钥($HOME/.ssh/id_ecdsa.pub$HOME/.ssh/id_ed25519.pub$HOME/.ssh/id_rsa.pub)发送给将您设置为提交者的用户,以便将其放入 freefall 上的 /etc/ssh-keys/ 中的 yourlogin 中。

现在,ssh-add(1) 可用于每次会话一次的身份验证。它会提示输入私钥的密码短语,然后将其存储在身份验证代理(ssh-agent(1))中。使用 ssh-add -d 删除存储在代理中的密钥。

使用简单的远程命令进行测试:ssh freefall.FreeBSD.org ls /usr

有关更多信息,请参阅 security/openssh-portablessh(1)ssh-add(1)ssh-agent(1)ssh-keygen(1)scp(1)

有关添加、更改或删除 ssh(1) 密钥的信息,请参阅 这篇文章

19. Coverity® 可用于 FreeBSD 提交者

所有 FreeBSD 开发人员都可以获得对所有 FreeBSD 项目软件的 Coverity 分析结果的访问权限。所有有兴趣获得对自动 Coverity 运行的分析结果的访问权限的人,可以在 Coverity Scan 上注册。

FreeBSD Wiki 包含一个供有兴趣使用 Coverity® 分析报告的开发人员使用的简要指南:https://wiki.freebsd.org/CoverityPrevent。请注意,此简要指南仅供 FreeBSD 开发人员阅读,因此如果您无法访问此页面,您将不得不请求某人将您添加到相应的 Wiki 访问列表中。

最后,所有将使用 Coverity® 的 FreeBSD 开发人员都鼓励随时提出更多详细信息和使用信息,方法是将任何问题发布到 FreeBSD 开发人员的邮件列表中。

20. FreeBSD 提交者的大规则清单

所有参与 FreeBSD 项目的人员都应遵守从 https://freebsd.ac.cn/internal/code-of-conduct 获取的行为准则。作为提交者,您是项目的公众形象,您的行为对公众对项目的看法有至关重要的影响。本指南扩展了行为准则中特定于提交者的部分。

  1. 尊重其他提交者。

  2. 尊重其他贡献者。

  3. 提交之前讨论任何重大更改。

  4. 尊重现有维护者(如果列在 Makefile 中的 MAINTAINER 字段或顶层目录中的 MAINTAINER 中)。

  5. 任何有争议的更改必须在维护者要求的情况下回滚,直到争议解决。安全相关更改可能会在安全主管的酌情权范围内覆盖维护者的意愿。

  6. 更改会先进入 FreeBSD-CURRENT,然后再进入 FreeBSD-STABLE,除非发布工程师特别允许,或者除非它们不适用于 FreeBSD-CURRENT。任何适用的非平凡或非紧急更改也应该在合并之前至少在 FreeBSD-CURRENT 中停留 3 天,以便对其进行充分测试。发布工程师对 FreeBSD-STABLE 分支拥有与规则#5 中概述的维护者相同的权限。

  7. 不要在公开场合与其他提交者争吵;看起来很不好。

  8. 尊重所有代码冻结,并及时阅读 committersdevelopers 邮件列表,以便您了解代码冻结何时生效。

  9. 如果有任何疑问,请先询问!

  10. 在提交更改之前,请测试您的更改。

  11. 未经相应维护者的明确批准,不要向贡献的软件提交代码。

如上所述,违反其中一些规则可能是导致暂停的理由,或者在反复违反的情况下,可能是永久撤销提交权限的理由。核心成员有权暂时暂停提交权限,直到整个核心有机会审查该问题。在出现“紧急情况”(提交者破坏存储库)的情况下,存储库管理员也可能暂时暂停。只有核心三分之二以上的多数成员有权暂停提交权限超过一周或永久撤销提交权限。这条规则存在的意义不是将核心塑造成一群可以像处理空易拉罐一样随意处理提交者的残酷独裁者,而是为了给项目提供一种安全保险。如果有人失控,重要的是能够立即处理这种情况,而不是因争论而陷入瘫痪。在所有情况下,提交权限被暂停或撤销的提交者都有权由核心进行“听证”,此时将确定暂停的总持续时间。提交权限被暂停的提交者也可以在 30 天后以及此后的每 30 天请求对决定的审查(除非总暂停时间少于 30 天)。提交权限已被完全撤销的提交者可以在 6 个月后请求审查。此审查政策严格来说是非正式的,在所有情况下,核心保留对审查请求进行处理或不予理会的权利,如果他们认为最初的决定是正确的。

在项目的其他所有运营方面,核心都是提交者的一个子集,受相同的规则约束。仅仅因为某人属于核心,并不意味着他们有特殊许可可以越界;核心的“特殊权力”只在它作为一个群体行动时才发挥作用,而不是在个人基础上发挥作用。作为个人,核心团队成员首先是提交者,其次才是核心。

20.1. 详细信息

  1. 尊重其他提交者。

    这意味着您需要像对待其他提交者一样对待他们,因为他们是您的同等开发者。尽管我们偶尔会试图证明相反,但一个人不会因为愚蠢而成为提交者,而没有什么比被你的同伴这样对待更令人恼火的了。无论我们是否始终尊重彼此(每个人都会有情绪不好的时候),我们仍然必须在任何时候,在公共论坛和私人邮件中都以尊重的方式对待其他提交者。

    能够长期合作是这个项目最大的资产,远比代码的任何更改更重要,而将有关代码的争论变成影响我们长期和谐合作能力的问题,从任何可以想象的角度来看都不值得这种权衡。

    为了遵守此规则,请不要在生气或以可能让其他人认为您不必要地对抗的方式行事时发送电子邮件。首先冷静下来,然后思考如何以最有效的方式进行沟通,说服其他人相信您一方的论点是正确的,而不要仅仅发泄一下情绪,以便您能在短期内感觉好一些,但代价是引发长期口水战。这不仅是非常糟糕的“能量经济学”,而且反复公开表现出攻击性行为,损害我们共同努力的能力,将受到项目领导层的严厉处理,并可能导致您被暂停或终止提交权限。项目领导层将考虑提交给它的公开和私人沟通。它不会寻求披露私人沟通,但如果提交者参与投诉并自愿提供私人沟通,它会将其考虑在内。

    所有这些都不是项目领导层最喜欢的选择,但团结最重要。再多的代码或好的建议都不值得拿它来换。

  2. 尊重其他贡献者。

    你并不总是提交者。曾经,你只是一名贡献者。请始终牢记这一点。记住你曾经寻求帮助和关注的感受。不要忘记,你作为贡献者所做的工作对你非常重要。记住当时的感受。不要打击、贬低或蔑视贡献者。尊重他们。他们是等待成为提交者的成员。他们对项目的意义与提交者一样重要。他们的贡献与你的贡献一样有效,也同样重要。毕竟,你成为提交者之前也做出了许多贡献。始终牢记这一点。

    请参考 尊重其他提交者 中提出的要点,并将其同样应用于贡献者。

  3. 提交之前讨论任何重大更改。

    代码库不是提交更改以进行正确性检查或进行争论的地方,这些操作应该先在邮件列表或使用 Phabricator 服务中进行。只有在达成类似共识的情况下才会进行提交。这并不意味着在纠正所有明显的语法错误或手册页拼写错误之前需要获得许可,只是在提出更改并非如此简单,需要一些反馈的情况下,最好先培养一种感觉。人们并不介意大范围的更改,只要结果明显优于之前的版本,他们只是不喜欢被这些更改惊到。确保一切都在正轨上的最佳方法是让一名或多名其他提交者审查代码。

    如有疑问,请申请审查!

  4. 请尊重已列出的现有维护人员。

    FreeBSD 的许多部分不属于“所有权”范畴,即任何特定个人在您对“他们的”区域进行更改时不会跳起来大喊大叫,但先进行检查仍然有益。我们使用的一种约定是在任何由一个或多个个人积极维护的包或子树的 Makefile 中添加维护者行;请参阅 源代码树指南和策略 以获取有关此方面的文档。如果代码部分有几个维护者,则由一个维护者对受影响区域进行的提交需要至少由另一个维护者审查。在“维护者”不明确的情况下,请查看相关文件的代码库日志,查看最近或主要是在该区域工作的人员。

  5. 任何有争议的更改必须在维护者要求的情况下回滚,直到争议解决。安全相关更改可能会在安全主管的酌情权范围内覆盖维护者的意愿。

    这在发生冲突时可能难以接受(当双方都坚信自己是正确的时),但版本控制系统使在进行持续争论时无需这样做,因为只需简单地撤销有争议的更改、让每个人都冷静下来,然后尝试找出最佳的处理方式,就会容易得多。如果更改最终证明是最佳的,可以轻松地将其恢复。如果最终证明不是最佳的,那么用户不必在每个人都在忙着争论其优点时忍受树中虚假的更改。人们很少要求在代码库中进行回滚,因为讨论通常会在提交发生之前就暴露不良或有争议的更改,但在这种罕见的情况下,回滚应该毫不犹豫地进行,以便我们能够立即开始讨论到底是虚假更改还是其他更改。

  6. 更改会先提交到 FreeBSD-CURRENT,然后再提交到 FreeBSD-STABLE,除非发布工程师明确允许,或更改不适用于 FreeBSD-CURRENT。任何不重要的或非紧急的更改,如果适用,也应该在合并之前在 FreeBSD-CURRENT 中保留至少 3 天,以便对其进行充分测试。发布工程师对 FreeBSD-STABLE 分支拥有与规则第 5 条中概述的相同权限。

    这是一个“不要争论”的问题,因为最终是发布工程师负责(并承担责任),如果更改最终证明是有害的。请尊重这一点,并在涉及 FreeBSD-STABLE 分支时,全力配合发布工程师。对于非专业观察者来说,FreeBSD-STABLE 的管理方式可能经常显得过于保守,但也要记住,保守主义应该是 FreeBSD-STABLE 的标志,与 FreeBSD-CURRENT 中的规则不同。如果更改立即合并到 FreeBSD-STABLE 中,那么让 FreeBSD-CURRENT 成为测试平台就没有意义了。更改需要让 FreeBSD-CURRENT 开发人员有机会进行测试,因此,除非 FreeBSD-STABLE 修复是关键的、时间敏感的或如此明显以至于无需进一步测试(手册页的拼写修复、明显的错误/错误修复等),否则请留出一些时间,然后再进行合并。换句话说,请使用常识。

    对安全分支(例如 releng/9.3)的更改必须由 安全官团队 <security-officer@FreeBSD.org> 的成员批准,或在某些情况下,由 发布工程团队 <re@FreeBSD.org> 的成员批准。

  7. 不要在公开场合与其他提交者争吵;看起来很不好。

    这个项目需要维护良好的公众形象,这种形象对我们所有人来说都非常重要,尤其是我们要继续吸引新成员加入的话。在某些情况下,尽管每个人都尽力克制,但脾气会失控,并会说出愤怒的言语。在这种情况下,最好的做法是将这种影响降到最低,直到每个人都冷静下来。不要在公共场合说出愤怒的言语,也不要将私人信件或其他私人通信转发到公共邮件列表、邮件别名、即时通讯频道或社交媒体网站。人们一对一交流的内容往往比他们在公共场合发表的内容要少得多,因此这种通信不应该出现在公共场合 - 这样做只会火上浇油。如果发送火焰邮件的人至少有足够的礼貌私下发送,那么请有足够的礼貌将它保密。如果您觉得您受到另一个开发人员的不公平待遇,并且这给您造成了痛苦,请与核心团队联系,而不是公开此事。核心团队会尽力调解,让事情恢复正常。如果争议涉及对代码库的更改,而参与者似乎无法达成友好协议,则核心团队可以指定一个双方都同意的第三方来解决争议。所有相关方必须同意受此第三方做出的决定的约束。

  8. 请尊重所有代码冻结,并及时阅读 committersdevelopers 邮件列表,以便您了解代码冻结何时生效。

    在代码冻结期间提交未经批准的更改是一个非常大的错误,提交者应该在长时间缺席后跳进来提交 10 MB 的累积内容之前,了解当前情况。定期滥用此权限的人员将被暂停提交权限,直到他们从我们在格陵兰岛举办的 FreeBSD 幸福再教育营回来。

  9. 如果有任何疑问,请先询问!

    许多错误都是因为有人着急,并且假设他们知道正确的方式。如果您以前没有做过,那么很有可能您实际上并不了解我们做事的方式,真的需要先问问,否则您将在公共场合出丑。询问“我该怎么做?”并不可耻。我们已经知道您是一个聪明的人,否则您就不会成为提交者。

  10. 在提交更改之前,请测试您的更改。

    如果您的更改是针对内核的,请确保您仍然可以编译 GENERIC 和 LINT。如果您的更改位于其他地方,请确保您仍然可以构建 world。如果您的更改是针对某个分支的,请确保您的测试是在运行该代码的机器上进行的。如果您有一个更改可能会破坏另一个体系结构,请务必在所有支持的体系结构上进行测试。请确保您的更改适用于 支持的工具链。请参阅 FreeBSD 内部页面 以获取可用资源的列表。随着其他体系结构添加到 FreeBSD 支持的平台列表中,相应的共享测试资源将变得可用。

  11. 未经相应维护者的明确批准,不要向贡献的软件提交代码。

    贡献软件是指位于 src/contribsrc/cryptosrc/sys/contrib 树下的所有软件。

    上面提到的树是用于贡献软件的,这些软件通常会被导入到供应商分支。在其中提交内容可能会在导入软件的更新版本时造成不必要的麻烦。一般而言,请考虑向供应商发送补丁。在维护者的许可下,补丁可以先提交到 FreeBSD。

    修改上游软件的原因多种多样,从想要严格控制紧密耦合的依赖关系到规范存储库中代码分发的可移植性不足。无论原因是什么,尽量减少分叉维护负担对其他维护人员来说都是很有帮助的。避免对文件进行微不足道的或外观上的更改,因为这会使之后的每次合并变得更加困难:这样的补丁需要在每次导入时手动重新验证。

    如果某个特定软件缺少维护者,我们鼓励您接管所有权。如果您不确定当前的维护者,请发送电子邮件到 FreeBSD 架构和设计邮件列表 并询问。

20.2. 多个体系结构的策略

FreeBSD 在最近的几个发布周期中添加了几个新的体系结构端口,它不再是仅限于 i386™ 的操作系统。为了使 FreeBSD 更容易在支持的平台之间移植,核心团队制定了以下规定

我们的 32 位参考平台是 i386,我们的 64 位参考平台是 amd64。主要的设计工作(包括主要的 API 和 ABI 更改)必须至少在一个 32 位平台和至少在一个 64 位平台上验证,最好是主要的参考平台,然后才能将其提交到源代码树。

开发人员还应了解我们针对硬件架构长期支持的层级策略。 此处的规则旨在为开发过程提供指导,与该部分列出的功能和架构要求不同。 在发布时,架构上功能支持的层级规则比开发过程中的更改规则更为严格。

20.3. 多个编译器的策略

FreeBSD 使用 Clang 和 GCC 构建。 该项目以谨慎和受控的方式进行,最大程度地利用这项额外工作带来的好处,同时将额外工作量降至最低。 支持 Clang 和 GCC 可提高用户的使用灵活性。 这些编译器各有优劣,支持两者可以让用户根据需要选择最佳编译器。 Clang 和 GCC 支持类似的 C 和 C++ 方言,因此需要相对少量的条件代码。 该项目通过使用这两个编译器的功能,获得了更高的代码覆盖率,并提高了代码质量。 通过支持此范围,该项目能够在更多用户环境中构建并利用更多 CI 环境,从而为用户带来更多便利,并为用户提供更多测试工具。 通过仔细限制支持的版本范围,使其仅限于这些编译器的现代版本,该项目避免了过度增加测试矩阵。 较旧和难以理解的编译器以及较旧的语言方言的支持非常有限,允许用户程序使用它们进行构建,但不会限制基本系统使用它们进行构建。 确切的平衡一直在不断发展,以确保额外工作带来的好处大于其带来的负担。 该项目过去曾支持非常旧的 Intel 编译器或旧版本的 GCC,但我们放弃了支持这些过时的编译器,转而支持一组精心挑选的现代编译器。 本节介绍了我们使用不同编译器的地方以及相关期望。

FreeBSD 项目提供了一个树内 Clang 编译器。 由于位于树内,此编译器是支持最多的编译器。 所有更改都必须使用它编译,然后才能提交。 针对更改,应使用此编译器进行完整测试(适当时)。

在任何时间点,FreeBSD 项目还支持一个或多个树外编译器。 目前,此编译器为 GCC 12.x。 理想情况下,提交者应使用此编译器进行测试编译,尤其是对于大型或有风险的更改。 此编译器作为 ${TARGET_ARCH}-gcc${VERSION} 软件包提供,例如 aarch64-gcc12riscv64-gcc12。 该项目运行自动化的 CI 作业,使用这些编译器构建所有内容。 提交者应修复其更改导致的作业中断问题。 提交者可以在必要时使用 CROSS_TOOLCHAIN=aarch64-gcc12CROSS_TOOLCHAIN=llvm15 等进行测试构建。

FreeBSD 项目在 github 上也有一些 CI 管道。 对于 github 上的拉取请求以及推送到 github 分支的一些分支,会运行许多交叉编译作业。 这些测试使用 Clang 的版本构建 FreeBSD,该版本有时在一段时间内会比树内编译器滞后一个主要版本。

FreeBSD 项目也在升级编译器。 Clang 和 GCC 都是快速变化的目标。 一些更改树中内容的工作,例如删除旧式 K&R 函数声明和定义,将在编译器落地之前落地到树中。 提交者应尽量注意这一点,并乐于调查代码或更改使用这些新编译器时出现的问题。 此外,在新的编译器版本落地到树中后,人们可能需要使用旧版本编译内容,因为可能存在未发现的回归问题。

除了编译器之外,LLVM 的 LLD 和 GNU 的 binutils 也被编译器间接使用。 提交者应注意汇编语法和链接器的功能的差异,并确保两种变体都正常工作。 这些组件将在 FreeBSD 的 CI 作业中针对 Clang 或 GCC 进行测试。

FreeBSD 项目提供标题文件和库,允许使用其他编译器构建不在基本系统中的软件。 这些标题文件支持将环境设置得尽可能严格,以支持 ANSI-C 的先前方言,追溯到 C89,以及我们庞大的端口集合发现的其他边缘情况。 此支持限制了在标题文件等地方放弃旧标准的范围,但不会限制将基本系统更新到更新的方言。 它也不要求基本系统以整体方式使用这些旧标准进行编译。 破坏此支持会导致端口集合中的软件包失败,因此应尽可能避免这种情况,并在容易解决时立即修复。

FreeBSD 构建系统目前可以适应这些不同的环境。 随着编译器中添加了新的警告,该项目会尝试修复它们。 但是,有时这些警告需要进行大量重构,因此会通过使用根据编译器版本评估为适当内容的 make 变量来以某种方式进行抑制。 开发人员应注意这一点,并确保所有特定于编译器的标志都已正确地进行了条件化。

20.3.1. 当前编译器版本

树内编译器目前为 Clang 15.x。 目前,GCC 12 和 Clang 12、13、14 和 15 在 github 和项目的 CI jenkins 作业中进行了测试。 目前正在进行将树准备好迎接 Clang 16 的工作。 项目支持的最旧分支拥有 Clang 12,因此构建的引导部分必须支持 Clang 主要版本 12 到 15。

20.4. 其他建议

在提交文档更改时,请在提交之前使用拼写检查器。 对于所有 XML 文档,请运行 make linttextproc/igor 验证格式指令是否正确。

对于手册页,请对该手册页运行 sysutils/mancktextproc/igor,以验证所有交叉引用和文件引用是否正确,以及手册页是否安装了所有适当的 MLINKS

不要将样式修复与新功能混合在一起。 样式修复是指任何不修改代码功能的更改。 将更改混合在一起会混淆功能更改(当要求查看修订之间的差异时),这会隐藏任何新错误。 不要将空格更改与对 doc/ 的内容更改混合在提交中。 差异中的额外混乱会使翻译人员的工作更加困难。 相反,请在单独的提交中进行任何样式或空格更改,并在提交消息中明确标注这些更改。

20.5. 弃用功能

如果需要从基本系统中的软件中删除功能,请尽可能遵循以下准则。

  1. 在手册页中(以及可能在发行说明中)提及选项、实用程序或接口已弃用。 使用弃用功能会导致生成警告。

  2. 选项、实用程序或接口将保留到下一个主要(点零)版本。

  3. 选项、实用程序或接口已删除,不再进行文档记录。 它现在已过时。 通常,在发行说明中记录其删除也是一个好主意。

20.6. 隐私和机密性

  1. FreeBSD 的大部分业务是在公开环境中进行的。

    FreeBSD 是一个开放项目。 这意味着,不仅任何人都可以使用源代码,而且大多数开发过程都公开接受公众审查。

  2. 某些敏感事项必须保持私密或处于保密状态。

    不幸的是,无法实现完全透明。 作为 FreeBSD 开发人员,您将拥有访问信息的某些特权。 因此,您应尊重某些机密性要求。 有时,机密性要求来自外部合作者,或具有特定的时限。 但是,大多数情况下,这是指不要发布私人通信。

  3. 安全主管对安全公告的发布拥有唯一控制权。

    在影响许多不同操作系统的安全问题方面,FreeBSD 通常需要提前访问权限才能准备协调发布的公告。 除非 FreeBSD 开发人员能够保证维护安全,否则将不会提供此类提前访问权限。 安全主管负责控制对漏洞信息的提前发布访问权限,以及控制所有公告的发布时间。 他可能会在机密条件下请求具有相关知识的任何开发人员的帮助,以准备安全修复程序。

  4. 与核心团队的通信将尽可能长时间地保持机密性。

    对核心团队的通信最初将被视为机密信息。 但是,最终,核心团队的大多数业务将被总结到每月或每季度的核心团队报告中。 将注意避免公布任何敏感细节。 有关某些特别敏感主题的记录可能根本不会在报告中公布,并将仅保留在核心团队的私人档案中。

  5. 访问某些商业敏感数据可能需要签署保密协议。

    访问某些商业敏感数据可能需要在保密协议下才能获得。 在签署任何具有约束力的协议之前,必须咨询 FreeBSD 基金会法律团队。

  6. 未经许可,不得公开私人通信。

    除了上述具体要求之外,还有一种普遍的期望,即在未征得所有相关方同意的情况下,不要发布开发人员之间的私人通信。 在将消息转发到公共邮件列表或将其发布到可供除原始通信方以外的其他人访问的论坛或网站之前,请征得许可。

  7. 在仅限项目或限制访问的通道上进行的通信必须保持私密性。

    类似于个人通信,某些内部通信通道(包括仅限 FreeBSD 提交者的邮件列表和限制访问的 IRC 通道)被视为私人通信。 发布来自这些来源的材料需要获得许可。

  8. 核心团队可以批准发布。

    在由于通信方数量众多而无法获得许可,或者在无理拒绝发布许可的情况下,核心团队可以批准发布应更广泛发布的此类私人事项。

21. 对多个架构的支持

FreeBSD 是一个高度可移植的操作系统,旨在运行在许多不同类型的硬件架构上。保持机器相关 (MD) 代码和机器无关 (MI) 代码的干净分离,以及尽量减少 MD 代码,是我们保持敏捷应对当前硬件趋势战略的重要组成部分。FreeBSD 支持的每个新硬件架构都会大幅增加代码维护、工具链支持和发布工程的成本。它也会显著增加有效测试内核更改的成本。因此,在保持少数几个被视为 FreeBSD “目标受众” 的关键架构强大的同时,区分对各种架构的支持级别有着强烈的动机。

21.1. 总体意图声明

FreeBSD 项目的目标是“生产级商用现货 (COTS) 工作站、服务器和高端嵌入式系统”。通过专注于这些环境中的一组狭窄的感兴趣架构,FreeBSD 项目能够保持高水平的质量、稳定性和性能,以及最大程度地减少项目中各个支持团队(如端口团队、文档团队、安全官员和发布工程团队)的工作量。硬件支持的多样性通过提供新功能和使用机会,为 FreeBSD 用户提供了更广泛的选择,但这些优势必须始终在与额外平台支持相关的现实世界维护成本方面进行仔细考虑。

FreeBSD 项目将平台目标区分成四个层级。每个层级都包含消费者可以依赖的保证列表,以及项目和开发人员履行这些保证的义务。这些列表定义了每个层级的最低保证。项目和开发人员可能会为特定层级提供超出最低保证的额外支持级别,但这种额外支持并不保证。每个平台目标都为每个稳定分支分配到特定的层级。因此,平台目标可能在并发稳定分支上分配到不同的层级。

21.2. 平台目标

对硬件平台的支持包含两个组成部分:内核支持和用户空间应用程序二进制接口 (ABI)。内核平台支持包括在硬件平台上运行 FreeBSD 内核所需的内容,例如机器相关的虚拟内存管理和设备驱动程序。用户空间 ABI 指定了用户进程与 FreeBSD 内核和基本系统库交互的接口。用户空间 ABI 包括系统调用接口、公共数据结构的布局和语义,以及传递给子例程的参数的布局和语义。ABI 的某些组件可能由规范定义,例如 C++ 异常对象的布局或 C 函数的调用约定。

FreeBSD 内核还使用 ABI(有时称为内核二进制接口 (KBI)),其中包括内核本身内部公共数据结构的语义和布局以及传递给公共函数的参数的布局和语义。

FreeBSD 内核可能支持多个用户空间 ABI。例如,FreeBSD 的 amd64 内核支持 FreeBSD amd64 和 i386 用户空间 ABI,以及 Linux x86_64 和 i386 用户空间 ABI。FreeBSD 内核应该支持“本机” ABI 作为默认 ABI。“ABI”通常与内核 ABI 共享某些属性,例如 C 调用约定、基本类型的尺寸等。

内核和用户空间 ABI 都定义了层级。在常见情况下,平台的内核和 FreeBSD ABI 被分配到同一层级。

21.2.1. 第 1 层级:完全支持的架构

第 1 层级平台是最成熟的 FreeBSD 平台。它们受到安全官员、发布工程和端口管理团队的支持。第 1 层级架构预计在 FreeBSD 操作系统的各个方面,包括安装和开发环境,都是生产级质量。

FreeBSD 项目为第 1 层级平台的消费者提供以下保证

  • 发布工程团队将提供官方 FreeBSD 发布映像。

  • 将为支持的版本提供安全建议和勘误通知的二进制更新和源代码补丁。

  • 将为支持的分支提供安全建议的源代码补丁。

  • 跨平台安全建议的二进制更新和源代码补丁通常将在公告发布时提供。

  • 用户空间 ABI 的更改通常会包含兼容性垫片,以确保针对平台为第 1 层级的任何稳定分支编译的二进制文件能够正确运行。这些垫片可能不会在默认安装中启用。如果未为 ABI 更改提供兼容性垫片,则发布说明中将清楚地记录缺少垫片的情况。

  • 对内核 ABI 的某些部分的更改将包含兼容性垫片,以确保针对分支上最旧的支持版本编译的内核模块能够正确运行。请注意,并非所有内核 ABI 部分都受到保护。

  • 端口团队将提供针对第三方软件的官方二进制软件包。对于嵌入式架构,这些软件包可能从不同的架构交叉构建。

  • 大多数相关的端口应该能够构建,或者拥有适当的过滤器以防止不合适的端口构建。

  • 所有第 1 层级架构上都应完全支持不固有地与平台相关的功能。

  • 针对旧的稳定分支编译的二进制文件使用功能和兼容性垫片可能在较新的主要版本中被删除。此类删除将在发布说明中清楚地记录。

  • 第 1 层级平台应该有完整的文档。基本操作将在 FreeBSD 手册中进行说明。

  • 第 1 层级平台将包含在源代码树中。

  • 第 1 层级平台应该通过树内工具链或外部工具链进行自托管。如果需要外部工具链,将提供外部工具链的官方二进制软件包。

为了保持第 1 层级平台的成熟度,FreeBSD 项目将维护以下资源来支持开发

  • 在 FreeBSD.org 集群或所有开发人员都可以轻松访问的其他位置提供构建和测试自动化支持。嵌入式平台可以使用 FreeBSD.org 集群中可用的模拟器代替实际硬件。

  • 包含在 make universemake tinderbox 目标中。

  • FreeBSD 集群之一中用于构建软件包(以原生方式或通过 qemu-user)的专用硬件。

总体而言,开发人员需要提供以下内容以维持平台的第 1 层级状态

  • 对源代码树的更改不应故意破坏第 1 层级平台的构建。

  • 第 1 层级架构必须拥有成熟、健康的使用者和活跃开发人员生态系统。

  • 开发人员应该能够在常用的非嵌入式第 1 层级系统上构建软件包。这可能意味着原生构建,如果非嵌入式系统通常可用于该平台,或者它可能意味着托管在其他第 1 层级架构上的交叉构建。

  • 更改不能破坏用户空间 ABI。如果需要 ABI 更改,则应通过使用符号版本控制或共享库版本提升来提供对现有二进制文件的 ABI 兼容性。

  • 合并到稳定分支的更改不能破坏内核 ABI 的受保护部分。如果需要内核 ABI 更改,则应修改更改以保留现有内核模块的功能。

21.2.2. 第 2 层级:开发和利基架构

第 2 层级平台是功能齐全但不太成熟的 FreeBSD 平台。它们不受安全官员、发布工程和端口管理团队的支持。

第 2 层级平台可能是仍在积极开发中的第 1 层级平台候选者。达到生命周期结束的架构也可能会从第 1 层级状态移至第 2 层级状态,因为维护系统处于生产级质量状态所需的资源可用性减少。支持良好的利基架构也可能是第 2 层级。

FreeBSD 项目为第 2 层级平台的消费者提供以下保证

  • 端口基础设施应包含对第 2 层级架构的基本支持,足以支持构建端口和软件包。这包括对诸如 ports-mgmt/pkg 等基本软件包的支持,但不能保证任意端口都可构建或正常运行。

  • 所有第 2 层级架构上应支持不固有地与平台相关的功能,即使功能尚未实现。

  • 第 2 层级平台将包含在源代码树中。

  • 第 2 层级平台应该通过树内工具链或外部工具链进行自托管。如果需要外部工具链,将提供外部工具链的官方二进制软件包。

  • 第 2 层级平台应提供功能正常的内核和用户空间,即使没有提供官方发布版。

为了保持第 2 层级平台的成熟度,FreeBSD 项目将维护以下资源来支持开发

  • 包含在 make universemake tinderbox 目标中。

总体而言,开发人员需要提供以下内容以维持平台的第 2 层级状态

  • 对源代码树的更改不应故意破坏第 2 层级平台的构建。

  • 第 2 层级架构必须拥有活跃的使用者和开发人员生态系统。

  • 虽然允许更改破坏用户空间 ABI,但应避免无端地破坏 ABI。重大用户空间 ABI 更改应限制在主要版本中。

  • 尚未在第 2 层级架构上实现的新功能应提供在这些架构上禁用它们的机制。

21.2.3. 第 3 层级:实验性架构

第 3 层级平台至少拥有部分 FreeBSD 支持。它们不受安全官员、发布工程和端口管理团队的支持。

第 3 层级平台是开发早期的架构,适用于非主流硬件平台,或者被认为是不太可能在未来广泛使用的遗留系统。对第 3 层级平台的初始支持可能存在于单独的存储库中,而不是主源代码存储库中。

FreeBSD 项目不对第 3 层级平台的消费者提供任何保证,也不承诺维护资源来支持开发。第 3 层级平台可能并不总是可构建的,任何内核或用户空间 ABI 都不能视为稳定。

21.2.4. 不支持的架构

其他平台不受项目以任何形式支持。项目以前将这些描述为第 4 层级系统。

平台过渡到不支持状态后,所有对平台的支持都将从源代码、端口和文档树中删除。请注意,只要平台在端口支持的分支中受支持,端口支持就应该保留。

21.3. 更改架构层级的策略

系统只能在 FreeBSD 核心团队的批准下从一个层级移动到另一个层级,核心团队将与安全主管、发布工程和端口管理团队协商做出决定。要将平台提升到更高的层级,必须在提升完成之前满足任何缺少的支持保证。

22. 端口特定常见问题解答

22.1. 添加新端口

22.1.1. 如何添加新端口?

将端口添加到树中相对简单。端口准备就绪后,如稍后所述 此处,您需要在该类别的 Makefile 中添加端口的目录条目。在这个 Makefile 中,端口按字母顺序排列,并添加到 SUBDIR 变量中,如下所示

	SUBDIR += newport

端口及其类别的 Makefile 准备就绪后,就可以提交新端口了

% git add category/Makefile category/newport
% git commit
% git push

不要忘记 为端口树设置 git 钩子,如此处所述;一个特殊的钩子已被开发用于验证该类别的 Makefile

22.1.2. 添加新端口时还需要注意哪些其他事项?

检查端口,最好确保它能正确编译和打包。

Porters Handbook’s Testing Chapter 中包含更详细的说明。请参阅 Portclippy / Portfmtpoudriere 部分。

您不一定非要消除所有警告,但要确保您已修复了简单的警告。

如果该端口来自之前从未为项目做出过贡献的提交者,请将该人的姓名添加到 FreeBSD 贡献者列表的 其他贡献者 部分。

如果端口是作为 PR 提交的,请关闭 PR。要关闭 PR,请将状态更改为 Issue Resolved,并将解决方案更改为 Fixed

如果由于某种原因无法使用 poudriere 测试新端口,则测试的最低限度包括以下步骤

# make install
# make package
# make deinstall
# pkg add package you built above
# make deinstall
# make reinstall
# make package

请注意,poudriere 是软件包构建的参考标准,如果端口无法在 poudriere 中构建,它将被删除。

22.2. 删除现有端口

22.2.1. 如何删除现有端口?

首先,请阅读有关存储库副本的部分。在删除端口之前,您必须验证是否有其他端口依赖于它。

  • 确保端口集合中没有对该端口的依赖关系

    • 端口的 PKGNAME 在最近的 INDEX 文件中只有一行。

    • 没有其他端口在它们的 Makefile 中包含对该端口的目录或 PKGNAME 的任何引用

      使用 Git 时,请考虑使用 git-grep(1),它比 grep -r 快得多。

  • 然后,删除端口

    • 使用 git rm 删除端口的文件和目录。

    • 在父目录 Makefile 中删除端口的 SUBDIR 列表。

    • ports/MOVED 中添加一个条目。

    • 如果端口存在,请将其从 ports/LEGAL 中删除。

或者,您可以使用 ports/Tools/scripts 中的 rmport 脚本。此脚本由 Vasil Dimov <vd@FreeBSD.org> 编写。当向 FreeBSD 端口邮件列表 发送有关此脚本的问题时,请同时抄送 Chris Rees <crees@FreeBSD.org>,他是目前的维护者。

22.3. 如何将端口移至新位置?

  1. 彻底检查端口集合中是否有任何对旧端口位置/名称的依赖关系,并更新它们。在 INDEX 上运行 grep 不够,因为某些端口的依赖关系是通过编译时选项启用的。建议对整个端口集合进行完整的 git-grep(1)

  2. 从旧类别 Makefile 中删除 SUBDIR 条目,并在新类别 Makefile 中添加 SUBDIR 条目。

  3. ports/MOVED 中添加一个条目。

  4. 搜索 ports/security/vuxml 中 xml 文件内的条目,并相应地调整它们。特别是,检查具有新名称的先前软件包,其版本可能包含新端口。

  5. 使用 git mv 移动端口。

  6. 提交更改。

22.4. 如何将端口复制到新位置?

  1. 使用 cp -R old-cat/old-port new-cat/new-port 复制端口。

  2. 将新端口添加到 new-cat/Makefile 中。

  3. 更改 new-cat/new-port 中的内容。

  4. 提交更改。

22.5. 端口冻结

22.5.1. 什么是“端口冻结”?

“端口冻结”是端口树在发布之前进入的一种受限制状态。它用于确保与发布一起发布的软件包的更高质量。它通常持续几周。在这段时间里,构建问题被修复,并构建了发布软件包。这种做法不再使用,因为发布的软件包是从当前稳定的季度分支构建的。

有关如何将提交合并到季度分支的更多信息,请参阅 将提交合并到季度分支的授权流程是什么?

22.6. 季度分支

22.6.1. 将提交合并到季度分支的授权流程是什么?

截至 2020 年 11 月 30 日,无需寻求明确的批准即可提交到季度分支。

22.6.2. 将提交合并到季度分支的流程是什么?

将提交合并到季度分支(由于历史原因,我们称之为 MFH)与在 src 存储库中 MFC 提交非常相似,因此基本上

% git checkout 2021Q2
% git cherry-pick -x $HASH
(verify everything is OK, for example by doing a build test)
% git push

其中 $HASH 是您要复制到季度分支的提交的哈希值。-x 参数确保 main 分支的哈希值 $HASH 包含在季度分支的新提交消息中。

22.7. 创建新类别

22.7.1. 创建新类别的流程是什么?

请参阅 Porter’s Handbook 中的 提出新类别。完成此流程后,PR 已分配给端口管理团队 <portmgr@FreeBSD.org>,由他们决定是否批准。如果他们批准,他们有责任

  1. 执行任何必要的移动操作。(这仅适用于物理类别。)

  2. 更新 ports/Mk/bsd.port.mk 中的 VALID_CATEGORIES 定义。

  3. 将 PR 分配回给您。

22.7.2. 实现新的物理类别需要做什么?

  1. 升级每个移动端口的 Makefile。不要将新类别连接到构建中。

    要执行此操作,您需要

    1. 更改端口的 CATEGORIES(这是练习的目的,请记住?)新类别排在第一位。这将有助于确保 PKGORIGIN 正确。

    2. 运行 make describe。由于您将在后面的步骤中运行的顶层 make index 是对整个端口层次结构进行的 make describe 的迭代,因此在此处捕获任何错误可以避免您稍后重新运行此步骤。

    3. 如果您想真正彻底,现在可能是运行 portlint(1) 的好时机。

  2. 检查 PKGORIGIN 是否正确。端口系统使用每个端口的 CATEGORIES 条目来创建其 PKGORIGIN,用于将已安装的软件包连接到构建它们的端口目录。如果此条目错误,常用的端口工具(例如 pkg-version(8)portupgrade(1))将失败。

    要执行此操作,请使用 chkorigin.sh 工具:env PORTSDIR=/path/to/ports sh -e /path/to/ports/Tools/scripts/chkorigin.sh。这将检查端口树中的每个端口,即使是那些未连接到构建的端口,因此您可以在移动操作后直接运行它。提示:不要忘记查看您刚刚移动的端口的任何从属端口的 PKGORIGIN

  3. 在您自己的本地系统上,测试建议的更改:首先,注释掉旧端口类别 Makefile 中的 SUBDIR 条目;然后在 ports/Makefile 中启用构建新类别。在受影响的类别目录中运行 make checksubdirs 以检查 SUBDIR 条目。接下来,在 ports/ 目录中,运行 make index。这即使在现代系统上也可能需要 40 分钟以上;但是,这是防止其他人遇到问题的必要步骤。

  4. 完成后,您可以提交更新的 ports/Makefile 以将新类别连接到构建中,还可以提交旧类别或类别的 Makefile 更改。

  5. ports/MOVED 中添加适当的条目。

  6. 通过修改以下内容来更新文档

  7. 只有在完成上述所有操作后,并且没有人再报告与新端口相关的问题时,才应该从存储库中的先前位置删除旧端口。

22.7.3. 实现新的虚拟类别需要做什么?

这比物理类别简单得多。只需要做一些修改

22.8. 其他问题

22.8.1. 是否存在不需要征得维护者批准即可提交的更改?

大多数端口的全面批准适用于以下类型的修复

  • 对端口的大多数基础设施更改(即现代化,但不改变功能)。例如,全面批准涵盖转换为新的 USES 宏、启用详细构建以及切换到新的端口系统语法。

  • 微不足道且经过测试的构建和运行时修复。

  • 端口的文档或元数据更改,例如 pkg-descrCOMMENT

对此的例外情况是端口管理团队 <portmgr@FreeBSD.org> 或安全主管团队 <security-officer@FreeBSD.org> 维护的任何内容。未经授权的提交永远不能对这些组维护的端口进行。

22.8.2. 如何知道我的端口是否构建正确?

这些软件包每周都会构建多次。如果端口失败,维护者将收到来自 pkg-fallout@FreeBSD.org 的电子邮件。

所有软件包构建(官方、实验和非回归)的报告都汇总在 pkg-status.FreeBSD.org 上。

22.8.3. 我添加了一个新的端口。我需要将其添加到 INDEX 中吗?

不需要。该文件可以通过运行 make index 生成,也可以通过 make fetchindex 下载预生成的版本。

22.8.4. 还有哪些文件我不允许修改?

任何直接位于 ports/ 下的文件,或任何位于以大写字母开头的子目录下的文件(例如 Mk/Tools/ 等)。特别地,端口管理团队 <portmgr@FreeBSD.org> 对 ports/Mk/bsd.port*.mk 非常保护,因此除非你希望面对他们的怒火,否则不要提交对这些文件的更改。

22.8.5. 当文件在没有版本变更的情况下更改时,更新端口分发文件的校验和的正确步骤是什么?

当分发文件的校验和由于作者更新了文件而没有更改端口版本而更新时,提交消息将包含原始分发文件和新分发文件之间相关差异的摘要,以确保分发文件没有被损坏或恶意更改。如果端口的当前版本已在端口树中存在了一段时间,通常可以在 ftp 服务器上获得旧分发文件的副本;否则,应联系作者或维护者以了解为什么分发文件发生了更改。

22.8.6. 如何请求端口树的实验性测试构建 (exp-run)?

在提交对端口有重大影响的补丁之前,必须完成 exp-run。补丁可以针对端口树或基本系统。

将使用提交者提供的补丁进行完整的软件包构建,并且要求提交者在提交之前修复发现的问题(fallout)

  1. 转到 Bugzilla 新 PR 页面

  2. 选择你的补丁所针对的产品。

  3. 像往常一样填写错误报告。请记住附加补丁。

  4. 如果顶部显示“显示高级字段”,请点击它。现在它将显示“隐藏高级字段”。许多新字段将可用。如果它已经显示“隐藏高级字段”,则无需执行任何操作。

  5. 在“标志”部分,将“exp-run”设置为 ?。至于所有其他字段,将鼠标悬停在任何字段上都会显示更多详细信息。

  6. 提交。等待构建运行。

  7. 端口管理团队 <portmgr@FreeBSD.org> 将回复可能出现的 fallout。

  8. 根据 fallout

    • 如果没有 fallout,则此处的流程停止,并且可以提交更改,前提是任何其他需要的批准都已获得。

      1. 如果有 fallout,则必须修复它,方法是直接在端口树中修复端口,或者将修复添加到提交的补丁中。

      2. 完成此操作后,返回步骤 6,说明 fallout 已修复,然后等待再次运行 exp-run。只要有损坏的端口,就重复此操作。

23. 非提交者开发人员特有的问题

一些可以访问 FreeBSD 机器的人没有提交权限。本文档中的几乎所有内容都适用于这些开发者(除了与提交和相关的邮件列表成员资格有关的特定内容)。我们建议您阅读

24. 关于 Google Analytics 的信息

自 2012 年 12 月 12 日起,FreeBSD 项目网站上启用了 Google Analytics,用于收集有关网站使用情况的匿名使用统计信息。

自 2022 年 3 月 3 日起,FreeBSD 项目已从 Google Analytics 中移除。

25. 其他问题

25.1. 如何访问 people.FreeBSD.org 以发布个人或项目信息?

people.FreeBSD.orgfreefall.FreeBSD.org 相同。只需创建一个 public_html 目录。您放置在该目录中的任何内容都会自动显示在 https://people.FreeBSD.org/ 下。

25.2. 邮件列表存档存储在哪里?

邮件列表存档在 freefall.FreeBSD.org 上的 /local/mail 下。

25.3. 我想指导一位新的提交者。我需要遵循什么流程?

请参阅内部页面上的 新帐户创建流程 文档。

26. FreeBSD 提交者的福利和津贴

26.1. 认可

作为一名称职的软件工程师得到认可是最持久的价值。此外,有机会与一些最优秀的工程师合作,这是每位工程师都会梦寐以求的福利!

26.2. FreeBSD 商城

FreeBSD 提交者可以在会议上从 FreeBSD 商城有限公司 免费获得一套 4 CD 或 DVD。

26.3. Gandi.net

Gandi 提供网站托管、云计算、域名注册和 X.509 证书服务。

Gandi 向所有 FreeBSD 开发者提供 E-rate 折扣。为了简化获得折扣的流程,首先创建一个 Gandi 帐户,填写账单信息并选择货币。然后使用您的 @freebsd.org 邮件地址向 non-profit@gandi.net 发送邮件,并说明您的 Gandi 账号。

26.4. rsync.net

rsync.net 为 UNIX 用户提供针对脱机备份优化的云存储。他们的服务完全在 FreeBSD 和 ZFS 上运行。

rsync.net 向 FreeBSD 开发者提供永久免费的 500 GB 帐户。只需使用您的 @freebsd.org 地址在 https://www.rsync.net/freebsd.html 上注册,即可获得此免费帐户。


最后修改时间:2024 年 11 月 2 日,作者:Jose Luis Duran