# 11.1.使用 Git 制作补丁

当某 Port 不是作者发布的最新版本时，请更新本地工作副本 **/usr/ports**。该 Port 可能已经被更新到新版本。

如果要处理多个 Port，使用 Git 来保持整个 Ports 最新可能会更加方便，正如在 [Using the Ports Collection](https://docs.freebsd.org/en/books/handbook/ports#ports-using) 中所描述的。这还可以跟踪所有 Port 的依赖项。

接下来的步骤是检查是否已经有一个更新待处理。为此，有两种方法。可以通过可搜索的界面访问 [FreeBSD 问题报告（PR）或 bug 数据库](https://bugs.freebsd.org/search/)，在 `Product` 的多选菜单中选择 `Ports & Packages`，然后在 `Summary` 字段中输入 Port 的名称。

如果没有待处理的 PR，接下来的步骤是向 Port 的维护者发送电子邮件，如通过 `make maintainer` 显示的那样。维护者可能已经在进行升级，或者有不升级该 Port 的理由（例如新版本可能存在稳定性问题），这时就没有必要重复他们的工作。注意，未维护的 Ports 会列出 `ports@FreeBSD.org` 作为维护者，这是一个通用的 Ports 邮件列表，因此在这种情况下发送邮件可能没有帮助。

如果维护者要求你进行升级，或者该 Port 没有维护者，那么可以帮助 FreeBSD 准备更新！可以使用基本系统中的 [diff(1)](https://man.freebsd.org/cgi/man.cgi?query=diff\&sektion=1\&format=html) 命令来完成。

要为单个补丁创建合适的 `diff`，将需要修补的文件复制为 **something.orig**，保存更改为 **something**，然后创建补丁：

```sh
% diff -u something.orig something > something.diff
```

否则，可以使用 `git diff` 方法（请参阅 [Using Git to Make Patches](https://docs.freebsd.org/en/books/porters-handbook/upgrading/#git-diff)）或者将 Port 的内容复制到另一个目录，并使用新的和旧的 Port 目录的递归 [diff(1)](https://man.freebsd.org/cgi/man.cgi?query=diff\&sektion=1\&format=html) 输出结果（例如，如果修改过的 Port 目录称为 **superedit**，原目录为 **superedit.bak**，则保存 `diff -ruN superedit.bak superedit` 的结果）。统一或上下文 diff 都可以，但 Port 提交者通常更喜欢统一格式的 diff。注意使用 `-N` 选项——这是处理新文件添加或旧文件删除的标准方法。在提交 diff 之前，请检查输出，确保所有更改都合理。（特别是，确保首先使用 `make clean` 清理工作目录。）

> **注意**
>
> 如果有文件被添加、复制、移动或删除，请将此信息添加到问题报告中，以便提交补丁的提交者知道需要执行哪些 [git(1)](https://man.freebsd.org/cgi/man.cgi?query=git\&sektion=1\&format=html) 命令。

为了简化常见的补丁操作，可以使用 `make makepatch`，如在 [Patching](https://docs.freebsd.org/en/books/porters-handbook/slow-porting/#slow-patch) 中所述。还可以使用其他工具，如 **/usr/ports/Tools/scripts/patchtool.py**。在使用之前，请阅读 **/usr/ports/Tools/scripts/README.patchtool**。

如果该 Port 没有维护者，并且你正在积极使用它，请考虑自愿成为它的维护者。FreeBSD 有超过 4000 个没有维护者的 Ports，这是一个总是需要更多志愿者的领域。（有关维护者职责的详细描述，请参阅 [Developer’s Handbook](https://docs.freebsd.org/en/books/developers-handbook/#POLICIES-MAINTAINER) 章节。）

要提交 diff，请使用 [bug 提交表单](https://bugs.freebsd.org/submit/)（产品 `Ports & Packages`，组件 `Individual Port(s)`）。始终在 Port 名称后附上类别，并简要描述问题。例如：`category/portname:<span> </span>add FOO option`；`category/portname:<span> </span>Update to X.Y`。请在消息中提到任何添加或删除的文件，因为在提交时需要明确指定这些文件给 [git(1)](https://man.freebsd.org/cgi/man.cgi?query=git\&sektion=1\&format=html)。不要压缩或编码 diff。

在提交问题报告之前，请查看 [Writing the problem report](https://docs.freebsd.org/en/articles/problem-reports/#pr-writing) 章节中的问题报告编写指南。它包含了有关如何编写有用问题报告的更多信息。

> **重要**
>
> 如果升级是出于安全考虑或当前提交的 Port 存在严重缺陷，请通知 Ports 管理团队 <<portmgr@FreeBSD.org>>，以请求立即重新构建和重新分发该 Port 的包。否则，使用 `pkg` 的用户将继续通过 `pkg install` 安装旧版本，可能会持续几周。

> **注意**
>
> 请使用 [diff(1)](https://man.freebsd.org/cgi/man.cgi?query=diff\&sektion=1\&format=html) 或 `git diff` 来创建现有 Ports 的更新。其他格式可能包括整个文件，使得无法仅查看更改内容。当没有包含 diff 时，整个更新可能会被忽略。

完成这些工作后，请阅读 [Keeping Up](https://docs.freebsd.org/en/books/porters-handbook/keeping-up/#keeping-up) 中关于如何保持更新的内容。

***

如果可能，请提交 [git(1)](https://man.freebsd.org/cgi/man.cgi?query=git\&sektion=1\&format=html) 补丁或 diff。相比于“新旧”目录之间的 diff，它们更容易处理。这样更容易看到变更内容，并且如果在开始工作后 Ports 集合中有所修改，或者提交者要求修复某些内容，可以更容易地更新 diff。此外，使用 [git-format-patch(1)](https://man.freebsd.org/cgi/man.cgi?query=git-format-patch\&sektion=1\&format=html) 或 [git-diff(1)](https://man.freebsd.org/cgi/man.cgi?query=git-diff\&sektion=1\&format=html) 生成的补丁，可以通过 [git-am(1)](https://man.freebsd.org/cgi/man.cgi?query=git-am\&sektion=1\&format=html) 或 [git-apply(1)](https://man.freebsd.org/cgi/man.cgi?query=git-apply\&sektion=1\&format=html) 轻松应用，并节省提交者的一些时间。最后，通过 [git-format-patch(1)](https://man.freebsd.org/cgi/man.cgi?query=git-format-patch\&sektion=1\&format=html) 生成的 Git 补丁包含你的作者信息和提交消息。这些信息将记录在仓库的日志中，这是提交更改的推荐方式。

```sh
% git clone https://git.FreeBSD.org/ports.git ~/my_wrkdir  ①②
% cd ~/my_wrkdir
```

* ① 当然，这个路径可以是任何位置。构建 Ports 并不限于 **/usr/ports/**。
* ② [git.FreeBSD.org](https://git.freebsd.org/) 是 FreeBSD 的公共 Git 服务器。有关更多信息，请参阅 [FreeBSD Git Repository URL Table](https://docs.freebsd.org/en/books/handbook/mirrors#git-url-table)。

在 Port 目录中，进行必要的更改。如果是添加、移动或删除文件，请使用 `git` 来跟踪这些更改：

```sh
% git add new_file
% git mv old_name new_name
% git rm deleted_file
```

确保使用 [Testing the Port](https://docs.freebsd.org/en/books/porters-handbook/quick-porting/#porting-testing) 和 [Checking the Port with `portlint`](https://docs.freebsd.org/en/books/porters-handbook/quick-porting/#porting-portlint) 中的检查清单来检查该 Port。

同时，使用 `make makesum` 更新 distinfo 中的校验和引用。

在制作补丁之前，获取最新的仓库并将更改 rebase 到其之上。仔细观察并跟踪输出。如果有任何文件 rebase 失败，意味着在你编辑同一个文件时，源文件发生了变化，需要手动解决冲突。

```sh
% git fetch origin main
% git rebase origin/main
```

检查待提交的更改：

```sh
% git status
% git diff --staged
```

最后一步是生成统一的 diff 或补丁：

要使用 [git-format-patch(1)](https://man.freebsd.org/cgi/man.cgi?query=git-format-patch\&sektion=1\&format=html) 生成补丁：

```sh
% git checkout -b my_branch
% git commit
% git format-patch main
```

这将生成一个类似于 `0001-foo.patch` 的补丁文件。这是推荐的方式，因为它包含了作者身份信息，而且当你进行一系列不打算合并在一起的更改时也更方便。

另外，要使用 [git-diff(1)](https://man.freebsd.org/cgi/man.cgi?query=git-diff\&sektion=1\&format=html) 生成统一的 diff，可以执行：

```sh
% git diff --staged > ../`make -VPKGNAME`.diff
```

这将生成一个类似于 `foo-1.2.3.diff` 的 diff 文件，其中 `foo` 替换为提交消息的第一行，即提交消息的主题。

补丁创建完成后，你可以切换回主分支开始其他开发工作。

```sh
% git checkout main
```

补丁被接受并合并后，你可以删除本地开发分支（如果你想的话）：

```sh
% git branch -D my_branch
```

> **注意**
>
> 如果文件已添加、移动或删除，请包含使用的 [git(1)](https://man.freebsd.org/cgi/man.cgi?query=git\&sektion=1\&format=html) `add`、`mv` 和 `rm` 命令。必须在补丁应用之前运行 `git mv`。应用补丁后，必须运行 `git add` 或 `git rm`。

按照 [问题报告提交指南](https://docs.freebsd.org/en/articles/problem-reports/#pr-writing) 提交补丁。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://porters-handbook.bsdcn.org/di-11-zhang-sheng-ji-port/11.1.-shi-yong-git-zhi-zuo-bu-ding.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
