设置和配置
获取和创建项目
基本快照
分支与合并
共享和更新项目
检查和比较
打补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.55.0 无变更
-
2.54.0
2026-04-20
- 2.53.0 无变更
-
2.52.0
2025-11-17
- 2.51.2 无变更
-
2.51.1
2025-10-15
- 2.50.1 → 2.51.0 无变更
-
2.50.0
2025-06-16
- 2.49.1 无更改
-
2.49.0
2025-03-14
- 2.46.1 → 2.48.2 无变更
-
2.46.0
2024-07-29
- 2.43.3 → 2.45.4 无变更
-
2.43.2
2024-02-13
-
2.43.1
2024-02-09
-
2.43.0
2023-11-20
- 2.42.1 → 2.42.4 无更改
-
2.42.0
2023-08-21
- 2.41.1 → 2.41.3 无更改
-
2.41.0
2023-06-01
- 2.39.1 → 2.40.4 无更改
-
2.39.0
2022-12-12
- 2.38.1 → 2.38.5 无更改
-
2.38.0
2022-10-02
- 2.37.1 → 2.37.7 无更改
-
2.37.0
2022-06-27
- 2.35.1 → 2.36.6 无更改
-
2.35.0
2022-01-24
- 2.34.1 → 2.34.8 无更改
-
2.34.0
2021-11-15
- 2.33.1 → 2.33.8 无更改
-
2.33.0
2021-08-16
- 2.31.1 → 2.32.7 无更改
-
2.31.0
2021-03-15
- 2.30.1 → 2.30.9 无更改
-
2.30.0
2020-12-27
- 2.29.1 → 2.29.3 无更改
-
2.29.0
2020-10-19
- 2.28.1 无更改
-
2.28.0
2020-07-27
- 2.26.1 → 2.27.1 无变更
-
2.26.0
2020-03-22
- 2.25.1 → 2.25.5 无更改
-
2.25.0
2020-01-13
- 2.24.1 → 2.24.4 无更改
-
2.24.0
2019-11-04
- 2.23.1 → 2.23.4 无更改
-
2.23.0
2019-08-16
此信息专用于 Git 项目
请注意,如果您打算为 Git 项目本身做贡献,此信息才与您相关。它绝不是普通 Git 用户的必读内容。
摘要
本教程演示了在 Git 树中创建变更、将其发送以供评审以及根据评审意见进行修改的端到端工作流。
相关阅读
本教程旨在总结以下文档,但读者可能会发现有用的补充背景信息
-
Documentation/SubmittingPatches -
Documentation/howto/new-command.adoc
获取帮助
如果您遇到困难,可以在以下地方寻求帮助。
git@vger.kernel.org
这是 Git 项目的主要邮件列表,代码评审、版本公告、设计讨论等都在这里进行。有兴趣做出贡献的人欢迎在这里提问。Git 列表要求仅使用纯文本邮件,并在回复邮件时倾向于使用行内回复(inline)和底部回复(bottom-posting);在所有对您的回复中,您都会被抄送(CC)。(可选)您可以通过发送电子邮件至 <git+subscribe@vger.kernel.org> 来订阅该列表(详见 https://subspace.kernel.org/subscribing.html)。该邮件列表的存档可以在浏览器中查看。
Libera Chat 上的 #git-devel
该 IRC 频道用于 Git 贡献者之间的交流。如果当前有人在线并且知道您问题的答案,您可以获得实时帮助。否则,您可以阅读历史聊天记录以查看是否有人回答了您。IRC 不允许离线私信,因此如果您尝试给某人发送私信然后退出 IRC,他们将无法回复您。最好在频道中提出您的问题,这样即使您断开连接,也可以得到解答,并且其他人也能从对话中学习。
Discord 上的 #discord
这是一个非官方的 Git Discord 服务器,适合所有人,从刚开始使用 Git 的人到开发 Git 的人。这是一个实时提问、分享技巧以及与更广泛的 Git 社区建立联系的好地方。
该服务器设有用于一般讨论的频道,以及面向 Git 使用者和开发者的专属频道。服务器的搜索功能还允许您查找以前的对话以及常见问题的解答。
快速入门
克隆 Git 仓库
Git 在许多地方都有镜像。从其中之一克隆仓库;https://git-scm.cn/downloads 建议最好的克隆地点之一是 GitHub 上的镜像。
$ git clone https://github.com/git/git git $ cd git
安装依赖项
要从源码构建 Git,您需要在系统上安装一些依赖项。有关所需内容的提示,您可以查看 INSTALL 文件,特别注意关于 Git 对外部程序 and 库的依赖关系的部分。该文档提到了一种无需安装即可“试运行”我们新鲜构建的 Git 的方法;这就是我们在本教程中将要使用的方法。
通过构建您在上一步中克隆的全新 Git,确保您的环境拥有您所需的一切
$ make
|
注意
|
Git 的构建是支持并行的。上面未包含 -j#,但您可以在这里和其他地方根据需要使用它。 |
动手编码!
|
注意
|
可以在 https://github.com/nasamuffin/git/tree/psuh 找到参考实现。 |
添加新命令
许多子命令都是作为内置命令(builtins)编写的,这意味着它们是用 C 语言实现的,并编译进主 git 可执行文件中。将非常简单的 psuh 命令作为内置命令来实现,将展示代码库的结构、内部 API,以及作为贡献者与评审者和维护者协同工作以将该更改集成到系统中的过程。
内置子命令通常在名为 "cmd_" 后接子命令名称的函数中实现,源文件以子命令命名并位于 builtin/ 目录中。因此,在 builtin/psuh.c 中实现您的命令是合乎逻辑的。创建该文件,并在其中为您的命令编写入口点函数,使其符合以下风格和签名
int cmd_psuh(int argc UNUSED, const char **argv UNUSED, const char *prefix UNUSED, struct repository *repo UNUSED)
需要注意的几点
-
子命令实现接受命令行参数的形式为
intargc+constchar**argv,就像main() 函数一样。 -
它还接受两个额外的参数,
prefix和repo。它们的含义要到很后面才会讨论。 -
因为第一个示例不会使用任何这些参数,所以您的编译器会发出关于未使用参数的警告。由于这四个参数的列表是添加新内置命令的 API 所强制要求的,因此您不能省略它们。相反,您要向它们中的每一个添加
UNUSED,以告诉编译器您**知道**自己(目前)还没有使用它。
我们还需要添加 psuh 的声明;打开 builtin.h,找到 cmd_pull 的声明,并在紧邻其前添加一行关于 psuh 的声明,以保持声明按字母顺序排序
int cmd_psuh(int argc, const char **argv, const char *prefix, struct repository *repo);
请务必在您的 psuh.c 中包含 #include "builtin.h"。您还需要包含 #include "gettext.h" 以使用与打印输出文本相关的函数。
继续在 cmd_psuh 函数中添加一些临时的 printf。这是一个不错的起点,因为我们现在可以添加构建规则并注册该命令了。
|
注意
|
您的临时文本以及您在本教程过程中添加的大部分文本都是面向用户的。这意味着它需要支持本地化。请查看 po/README 下的“标记待翻译字符串”部分。在整个教程中,我们将根据需要标记待翻译的字符串;您将来在编写面向用户的命令时也应该这样做。 |
int cmd_psuh(int argc UNUSED, const char **argv UNUSED,
const char *prefix UNUSED, struct repository *repo UNUSED)
{
printf(_("Pony saying hello goes here.\n"));
return 0;
}
让我们尝试构建它。打开 Makefile,找到将 builtin/pull.o 添加到 BUILTIN_OBJS 的位置,并以同样的方式在其旁按字母顺序添加 builtin/psuh.o。完成此操作后,转到顶级目录,直接使用 make 进行构建。还要添加 DEVELOPER=1 变量以开启一些额外的警告
$ echo DEVELOPER=1 >config.mak $ make
|
注意
|
当您开发 Git 项目时,最好使用 DEVELOPER 标志;如果由于某种原因它不适用于您,您可以将其关闭,但最好向邮件列表提及该问题。 |
太好了,现在您的新命令可以顺利地独立构建了。但还没有人调用它。让我们来改变这一点。
命令列表位于 git.c 中。我们可以通过向 commands[] 数组中添加一个 cmd_struct 来注册一个新命令。struct cmd_struct 接受包含命令名称的字符串、指向命令实现的函数指针以及设置选项标志。目前,让我们继续模仿 push。找到注册 cmd_push 的那一行,复制它并针对 cmd_psuh 进行修改,将新行按字母顺序放置(紧接在 cmd_pull 之前)。
这些选项在 builtin.h 的“添加新的内置命令”下有详细文档。由于我们希望稍后能打印一些有关用户当前工作区上下文的数据,因此我们需要一个 Git 目录,所以选择 RUN_SETUP 作为您的唯一选项。
继续再次构建。您应该会看到一次干净的构建,现在让我们来试用一下看看是否有效。在 bin-wrappers 目录中有一个您可以用来进行测试的二进制文件。
$ ./bin-wrappers/git psuh
瞧!您已经拥有一个新命令了!干得好!让我们提交这个。
git status 显示已修改的 Makefile、builtin.h 和 git.c,以及未跟踪的 builtin/psuh.c 和 git-psuh。首先,让我们处理一下该二进制文件,它应该被忽略。在编辑器中打开 .gitignore,找到 /git-pull,然后按字母顺序为您的新命令添加一个条目
... /git-prune-packed /git-psuh /git-pull /git-push /git-quiltimport /git-range-diff ...
再次检查 git status,应该会显示 git-psuh 已从未跟踪列表中移除,且 .gitignore 已添加到已修改列表中。现在我们可以暂存并提交了
$ git add Makefile builtin.h builtin/psuh.c git.c .gitignore $ git commit -s
系统将向您显示编辑器以便您编写提交说明。提交说明的第一行应是一个长度不超过 50 个字符的主题行,其中包括您正在处理的组件的名称,紧接着是一个空行(这是必须的),然后是提交说明的正文,正文应提供大部分上下文背景。请记住要写得清晰明确,并提供您进行更改的“原因”,特别是当它无法轻松从您的 diff 中看出时。在编辑您的提交说明时,请不要移除由上面的 -s 添加的 Signed-off-by 尾注(trailer)。
psuh: add a built-in by popular demand Internal metrics indicate this is a command many users expect to be present. So here's an implementation to help drive customer satisfaction and engagement: a pony which doubtfully greets the user, or, a Pony Saying "Um, Hello" (PSUH). This commit message is intentionally formatted to 72 columns per line, starts with a single line as "commit message subject" that is written as if to command the codebase to do something (add this, teach a command that). The body of the message is designed to add information about the commit that is not readily deduced from reading the associated diff, such as answering the question "why?". Signed-off-by: A U Thor <author@example.com>
继续使用 git show 检查您的新提交。"psuh:" 表示您主要修改了 psuh 命令。主题行让读者了解您修改了什么。签名行(-s)表示您同意《开发者原创证书(Developer’s Certificate of Origin)1.1》(参见 Documentation/SubmittingPatches 的 [[dco]] 标题)。
在教程的其余部分中,为了简明起见,将仅列出主题行。不过,完整的提交说明示例可以在本文档顶部链接的参考实现中找到。
具体实现
除了打印出字符串之外,让它至少能做点别的事情可能会很有用。让我们先来看看我们能获得的所有内容。
修改您的 cmd_psuh 实现,使其打印传递给您的参数,并保留现有的 printf() 调用;因为参数现在被使用了,请从它们中移除 UNUSED 宏
int i;
...
printf(Q_("Your args (there is %d):\n",
"Your args (there are %d):\n",
argc),
argc);
for (i = 0; i < argc; i++)
printf("%d: %s\n", i, argv[i]);
printf(_("Your current working directory:\n<top-level>%s%s\n"),
prefix ? "/" : "", prefix ? prefix : "");
构建并尝试运行它。正如您所预料的,基本上只有我们在命令行上给出的内容,包括我们的命令名称。(如果对您来说 prefix 为空,请尝试运行 cd Documentation/ && ../bin-wrappers/git psuh)。这并没有太大用处。那么我们还能获取什么其他上下文信息呢?
添加一行 #include "config.h"、#include "repository.h" 和 #include "environment.h"。然后,将以下内容添加到函数体中:函数体
const char *cfg_name;
...
repo_config(repo, git_default_config, NULL);
if (repo_config_get_string_tmp(repo, "user.name", &cfg_name))
printf(_("No name is found in config\n"));
else
printf(_("Your name: %s\n"), cfg_name);
repo_config() 将从 Git 已知的配置文件中抓取配置,并应用标准优先级规则。repo_config_get_string_tmp() 将查找特定键 ("user.name") 并向您提供对应的值。有很多类似于这样的单键查找函数;您可以在 config.h 中看到它们全部(以及关于如何使用 repo_config() 的更多信息)。
您应该会看到打印出的名称与您运行以下命令时看到的相匹配:
$ git config --get user.name
太棒了!现在我们知道如何检查 Git 配置中的值了。我们也提交这个吧,这样我们就不会丢失我们的进度。
$ git add builtin/psuh.c $ git commit -sm "psuh: show parameters & config opts"
|
注意
|
同样,以上内容在本教程中是为了简明起见。在实际的更改中,您不应该使用 -m,而是应该使用编辑器来编写有意义的提交说明。 |
即便如此,能知道用户的工作上下文状况也是极好的。让我们看看是否可以打印出用户当前分支的名称。我们可以模仿 git status 的实现;其打印器位于 wt-status.c 中,我们可以看到分支信息保存在一个 struct wt_status 中。
wt_status_print() 由 builtin/commit.c 中的 cmd_status() 调用。查看该实现,我们会看到状态配置像这样被填充
status_init_config(&s, git_status_config);
但是当我们深入研究时,我们会发现 status_init_config() 封装了对 repo_config() 的调用。让我们修改我们在上一次提交中编写的代码。
请务必包含允许您使用 struct wt_status 的头文件
#include "wt-status.h"
然后修改您的 cmd_psuh 实现,以声明您的 struct wt_status,准备它,并打印其内容
struct wt_status status;
...
wt_status_prepare(repo, &status);
repo_config(repo, git_default_config, &status);
...
printf(_("Your current branch: %s\n"), status.branch);
再次运行它。瞧——这就是您当前分支的(详细)名称!
我们也把这个提交了。
$ git add builtin/psuh.c $ git commit -sm "psuh: print the current branch"
现在让我们看看是否可以获取有关特定提交的一些信息。
幸运的是,这里有一些辅助函数可供我们使用。commit.h 有一个名为 lookup_commit_reference_by_name 的函数,我们可以简单地为其提供一个硬编码的字符串;pretty.h 有一个非常方便的 pp_commit_easy() 调用,它不需要传递完整的格式化对象。
添加以下 include 头文件
#include "commit.h" #include "pretty.h" #include "strbuf.h"
然后,在您的 cmd_psuh() 实现中的声明和逻辑附近分别添加以下几行。
struct commit *c = NULL;
struct strbuf commitline = STRBUF_INIT;
...
c = lookup_commit_reference_by_name("origin/master");
if (c != NULL) {
pp_commit_easy(CMIT_FMT_ONELINE, c, &commitline);
printf(_("Current commit: %s\n"), commitline.buf);
}
struct strbuf 为您的基础 char* 提供了一些安全保障,其中之一是用于防止缓冲区溢出的长度成员(length)。它需要使用 STRBUF_INIT 妥善初始化。当您需要传递 char* 时,请记住这一点。
lookup_commit_reference_by_name 会解析您传递给它的名称,因此您可以尝试修改该值,看看能得到什么结果。
pp_commit_easy 是 pretty.h 中的一个便利封装,它接受单个格式枚举简写,而不是整个格式结构。然后它根据该简写美化打印(pretty-print)提交。这与许多 Git 命令中可用的 --pretty=FOO 格式类似。
构建并运行它,如果您在示例中使用相同的名称,您应该会看到您所知道的 origin/master 中最新提交的主题行。真棒!我们也提交这个吧。
$ git add builtin/psuh.c $ git commit -sm "psuh: display the top of origin/master"
添加文档
太棒了!您已经拥有一个很棒的新命令,准备好与社区分享。但是等一下——这还不太用户友好。运行以下命令:
$ ./bin-wrappers/git help psuh
您的新命令还没有文档!让我们来解决这个问题。
看一下 Documentation/git-*.adoc。这些是 Git 所知道的子命令的联机帮助页(manpages)。您可以打开这些文件看一看以熟悉其格式,然后继续创建一个新文件 Documentation/git-psuh.adoc。与 Git 项目中的大多数文档一样,帮助页面也是用 AsciiDoc 编写的(参见 CodingGuidelines 的“编写文档”部分)。使用以下模板来填写您自己的 manpage
git-psuh(1) =========== NAME ---- git-psuh - Delight users' typo with a shy horse SYNOPSIS -------- [synopsis] git psuh [<arg>...] DESCRIPTION ----------- ... OPTIONS[[OPTIONS]] ------------------ ... OUTPUT ------ ... GIT --- Part of the git[1] suite
需要注意的最重要部分是文件标题(下划线为 =)、NAME(名称)部分以及 SYNOPSIS(大纲)部分——如果您的命令接受参数,大纲部分通常会包含其语法规则。尽量使用通用的帮助页标题,使您的文档与其他的 Git 和 UNIX 帮助页保持一致;这可以让您的用户过得更轻松,他们可以直接跳到他们知道包含所需信息的部分。
|
注意
|
在尝试构建文档之前,请确保您已安装了 asciidoc 软件包。 |
现在您已经编写了帮助页,您需要显式地构建它。我们将您的 AsciiDoc 转换为可由 man 阅读的 troff 格式,如下所示
$ make all doc $ man Documentation/git-psuh.1
或
$ make -C Documentation/ git-psuh.1 $ man Documentation/git-psuh.1
虽然这不如运行 git help 那么令人满意,但您至少可以检查您的帮助页面看起来是否正确。
您还可以在顶层目录下运行 make check-docs,来检查文档覆盖率是否良好(即,项目检测到您的命令既已实现又已编写文档)。
继续提交您的新文档更改。
添加使用说明文本
试着运行 ./bin-wrappers/git psuh -h。您的命令最后应该会崩溃。这是因为 -h 是一个特殊情况,您的命令应该通过打印使用说明来处理它。
看看 Documentation/technical/api-parse-options.adoc。这是一个提取您需要处理的选项的便捷工具,它接受一个使用说明字符串。
为了使用它,我们需要准备一个以 NULL 结尾的使用说明字符串数组和一个 builtin_psuh_options 数组。
添加一行 #include "parse-options.h"。
在全局作用域内,添加您的使用说明字符串数组
static const char * const psuh_usage[] = {
N_("git psuh [<arg>...]"),
NULL,
};
然后,在您的 cmd_psuh() 实现中,我们可以声明并填充我们的 option 结构体。我们的结构体非常单调,但如果您想更详细地探索 parse_options(),可以向其添加更多内容
struct option options[] = {
OPT_END()
};
最后,在打印参数和前缀之前,添加对 parse_options() 的调用
argc = parse_options(argc, argv, prefix, options, psuh_usage, 0);
此调用将修改您的 argv 参数。它将从 argv 中剥离您在 options 中指定的选项,并且 options 条目所指向的位置将会被更新。请务必将您的 argc 替换为 parse_options() 的结果,否则如果您稍后尝试解析 argv,将会感到困惑。
特别值得注意的是特殊参数 --。您可能知道,许多 Unix 命令使用 -- 来表示“命名参数结束”——-- 之后的所有参数仅被解释为位置参数。(如果您想将通常会被解释为标志的内容作为参数传递,这会很方便。)当 parse_options() 遇到 -- 时将终止解析,并保持原样返回其余的选项。
现在您有了一个使用说明提示,您可以教 Git 如何在由 git help git 或 git help -a 显示的常规命令列表中显示它(该列表是由 command-list.txt 生成的)。找到 *git-pull* 对应的行,以便您可以按字母顺序在其上方添加您的 *git-psuh* 行。现在,我们可以添加一些有关该命令的属性,这会影响它在上述帮助命令中出现的位置。command-list.txt 的顶部共享了有关每个属性含义的一些信息;在这些帮助页面中,命令是根据这些属性进行排序的。git psuh 是面向用户的外设命令(porcelain),所以我们会将其标记为 "mainporcelain"(主外设命令)。对于 "mainporcelain" 命令,command-list.txt 顶部的注释表明我们还可以选择从另一个列表中添加一个属性;由于 git psuh 显示了一些有关用户工作区的信息但没有修改任何内容,因此我们将其标记为 "info"。请确保您的属性格式与 command-list.txt 的其余部分保持相同的风格,使用空格进行对齐和勾勒。
git-prune-packed plumbingmanipulators git-psuh mainporcelain info git-pull mainporcelain remote git-push mainporcelain remote
再次构建。现在,当您使用 -h 运行命令时,您应该会看到打印出的使用说明,并且在发生其他任何有趣的事情之前命令已经终止。太棒了!
继续也把这一个提交。
测试
测试您的代码非常重要——即使是像这个玩具命令一样的小命令。此外,如果没有测试,您的补丁将不会被合并到 Git 树中。您的测试应当:
-
说明该功能的当前行为
-
证明当前行为符合预期行为
-
确保外部可见的行为在以后的修改中不会被破坏
所以让我们来编写一些测试。
相关阅读:t/README
编写您的测试
由于这是一个玩具命令,让我们继续将测试命名为 t9999。但是,由于许多系列/子命令组合已经满了,最佳实践 seems 是找到一个与您添加的命令足够接近的命令,并共享其命名空间。
创建一个新文件 t/t9999-psuh-tutorial.sh。像这样以头部信息开始(参见 t/README 中的“编写测试”和“引入 test-lib.sh”)
#!/bin/sh test_description='git-psuh test This test runs git-psuh and makes sure it does not crash.' . ./test-lib.sh
测试被封装在 test_expect_success 中,以便输出 TAP 格式的结果。让我们确保 git psuh 不会异常退出,并且确实在某处提到了正确的动物
test_expect_success 'runs correctly with no args and good output' ' git psuh >actual && grep Pony actual '
在脚本底部添加以下内容,表示您已经运行了所有想要运行的内容
test_done
确保您将您的测试脚本标记为可执行文件
$ chmod +x t/t9999-psuh-tutorial.sh
您可以通过运行 make -C t test-lint 来了解您是否成功创建了新的测试脚本,这将检查测试编号的唯一性、可执行位等。
在本地运行
让我们试着在本地运行
$ make $ cd t/ && prove t9999-psuh-tutorial.sh
您可以运行完整的测试套件,并确保 git-psuh 没有破坏任何东西
$ cd t/ $ prove -j$(nproc) --shuffle t[0-9]*.sh
|
注意
|
您也可以通过 make test 来执行此操作,或者使用任何支持 TAP 的测试工具。prove 可以并发运行。-j$(nproc) 使用所有可用的 CPU 并行运行测试,但任务数量可以根据需要进行调整。shuffle 会随机化测试的运行顺序,这使它们能够不受不需要的测试间依赖关系的影响。prove 还会使输出更加整洁。 |
继续也提交此项更改。
准备分享:补丁系列剖析
您可能已经注意到,Git 项目通过发送邮件补丁来进行代码评审,当补丁准备就绪并获得社区批准后,维护者会应用这些补丁。Git 项目不接受来自拉取请求(pull requests)的贡献,并且通过电子邮件发送以供评审的补丁需要以特定方式进行格式化。
在了解如何将您的提交转换为电子邮件补丁之前,让我们分析一下最终结果,即“补丁系列”长什么样。这里是 Git 邮件列表存档网页界面上一个补丁系列摘要视图的示例
2022-02-18 18:40 [PATCH 0/3] libify reflog John Cai via GitGitGadget 2022-02-18 18:40 ` [PATCH 1/3] reflog: libify delete reflog function and helpers John Cai via GitGitGadget 2022-02-18 19:10 ` Ævar Arnfjörð Bjarmason [this message] 2022-02-18 19:39 ` Taylor Blau 2022-02-18 19:48 ` Ævar Arnfjörð Bjarmason 2022-02-18 19:35 ` Taylor Blau 2022-02-21 1:43 ` John Cai 2022-02-21 1:50 ` Taylor Blau 2022-02-23 19:50 ` John Cai 2022-02-18 20:00 ` // other replies elided 2022-02-18 18:40 ` [PATCH 2/3] reflog: call reflog_delete from reflog.c John Cai via GitGitGadget 2022-02-18 19:15 ` Ævar Arnfjörð Bjarmason 2022-02-18 20:26 ` Junio C Hamano 2022-02-18 18:40 ` [PATCH 3/3] stash: call reflog_delete from reflog.c John Cai via GitGitGadget 2022-02-18 19:20 ` Ævar Arnfjörð Bjarmason 2022-02-19 0:21 ` Taylor Blau 2022-02-22 2:36 ` John Cai 2022-02-22 10:51 ` Ævar Arnfjörð Bjarmason 2022-02-18 19:29 ` [PATCH 0/3] libify reflog Ævar Arnfjörð Bjarmason 2022-02-22 18:30 ` [PATCH v2 0/3] libify reflog John Cai via GitGitGadget 2022-02-22 18:30 ` [PATCH v2 1/3] stash: add test to ensure reflog --rewrite --updatref behavior John Cai via GitGitGadget 2022-02-23 8:54 ` Ævar Arnfjörð Bjarmason 2022-02-23 21:27 ` Junio C Hamano // continued
我们可以注意以下几点
-
每个提交都是作为一封单独的电子邮件发送的,提交说明标题作为主题,对于包含 n 个提交的系列的第 i 个提交,前缀为 "[PATCH i/n]"。
-
每个补丁都是作为对该系列引言电子邮件(称为“封面信(cover letter)”)的回复发送的,前缀为 "[PATCH 0/n]"。
-
补丁系列的后续迭代被标记为 "PATCH v2"、"PATCH v3" 等,以代替 "PATCH"。例如,"[PATCH v2 1/3]" 将是第二次迭代中三个补丁中的第一个。每次迭代都会发送一个新的封面信(例如上面的 "[PATCH v2 0/3]"),它本身是对上一次迭代封面信的回复(详见下文)。
|
注意
|
单补丁主题在发送时带有 "[PATCH]"、"[PATCH v2]" 等,没有 i/n 编号(但在上面的主题线索概述中,没有出现单补丁主题)。 |
封面信 (Cover Letter)
除了为每个补丁发送一封电子邮件之外,Git 社区还期望您的补丁附带一封封面信。这是提交更改的一个重要组成部分,因为它可以从高层次向社区解释您试图做什么以及为什么这样做,其方式比仅仅看您的补丁更为直观。
封面信的标题应该能够简洁地涵盖您整个主题分支的目的。它通常采用祈使语气,就像我们的提交说明标题一样。以下我们将如何为我们的系列命名
添加 psuh 命令 ---
封面信的正文用于为评审者提供额外的上下文信息。请务必解释任何您补丁本身未能说清楚的内容,但请记住,由于封面信不会记录在提交历史中,因此任何可能对仓库历史的未来读者有用的内容也应该包含在您的提交说明中。
以下是 psuh 的示例正文
Our internal metrics indicate widespread interest in the command git-psuh - that is, many users are trying to use it, but finding it is unavailable, using some unknown workaround instead. The following handful of patches add the psuh command and implement some handy features on top of it. This patchset is part of the MyFirstContribution tutorial and should not be merged.
此时本教程将分为两部分,以演示格式化您的补丁集并使其接受评审的两种不同方法。
要介绍的第一种方法是 GitGitGadget,这对于那些已经熟悉 GitHub 常见的拉取请求工作流的人非常有用。此方法需要一个 GitHub 帐户。
要介绍的第二种方法是 git send-email,它可以对要发送的电子邮件进行稍微更细粒度的控制。此方法需要进行一些设置,这些设置可能会因系统而异,本教程将不予涵盖。
无论您选择哪种方法,您与评审者的互动都是一样的;评审过程将在有关 GitGitGadget 和 git send-email 的章节之后进行介绍。
通过 GitGitGadget 发送补丁
发送补丁的一个选择是遵循典型的拉取请求工作流,并通过 GitGitGadget 发送您的补丁。GitGitGadget 是 Johannes Schindelin 创建的一个工具,旨在为习惯了 GitHub PR 工作流的 Git 贡献者提供便利。它允许贡献者针对其 Git 项目镜像开启拉取请求,并施展魔法将 PR 转化为一组电子邮件并替您发送出去。它还会为您运行 Git 持续集成套件。其文档位于 https://gitgitgadget.github.io/。
在 GitHub 上派生(Fork)git/git
在您使用 GitGitGadget 发送您的补丁以供评审之前,您需要派生(fork)Git 项目并上传您的更改。首先——确保您拥有一个 GitHub 帐户。
前往 GitHub 镜像并寻找 Fork 按钮。将您的派生项目放置在您认为合适的任何位置并创建它。
上传到您自己的派生仓库
要将您的分支上传到您自己的派生仓库中,您需要将该新派生仓库添加为远程仓库。您可以使用 git remote -v 来显示您已经添加的远程仓库。在 GitHub 上您新派生仓库的页面上,您可以按 "Clone or download" 来获取 URL;然后您需要运行以下命令来添加它,在所提供的示例中替换您自己的 URL 和远程仓库名称
$ git remote add remotename git@github.com:remotename/git.git
或者使用 HTTPS URL
$ git remote add remotename https://github.com/remotename/git/.git
再次运行 git remote -v,您应该会看到新的远程仓库出现。运行 git fetch remotename(替换为您远程仓库的真实名称)以便为推送做好准备。
接下来,通过运行 git branch 仔细检查您是否一直在新分支中进行所有开发。如果没有,现在是把您的新提交移动到它们自己的分支中的好时机。
正如本文档开头简要提到的,我们将工作基于 master,因此请继续按照下方所示进行更新,或使用您首选的工作流。
$ git checkout master $ git pull -r $ git rebase master psuh
最后,您准备好推送您的新主题分支了!(由于我们的分支和命令名称的选择,在键入以下命令时请多加小心。)
$ git push remotename psuh
现在您应该能够前往 GitHub 查看您新创建的分支了。
向 GitGitGadget 发送 PR
为了对您的代码进行测试和格式化以供评审,您需要首先针对 gitgitgadget/git 或 git/git 开启一个拉取请求(Pull Request)。前往 https://github.com/gitgitgadget/git 或 https://github.com/git/git,通过 "New pull request" 按钮,或者针对您新推送的分支名称可能出现的便捷的 "Compare & pull request" 按钮来开启一个 PR。
使用 gitgitgadget/git 和 git/git 作为基础的区别可以在 [这里](https://gitgitgadget.github.io/#should-i-use-gitgitgadget-on-gitgitgadgets-git-fork-or-on-gits-github-mirror) 找到。
检查 PR 的标题和描述,因为它们分别被 GitGitGadget 用作您更改的封面信的主题和正文。有关如何为您提交的内容命名以及描述中应包含哪些内容的建议,请参阅上文的 “封面信”。
|
注意
|
对于单补丁贡献,您的提交说明应该已经很有意义,并从高层次解释了您补丁的目的(正在发生什么以及为什么),因此您通常不需要任何额外的上下文背景。在这种情况下,请删除 GitHub 根据您的提交说明自动生成的 PR 描述(您的 PR 描述应该为空)。如果您确实需要提供更多背景信息,您可以在该空白处提供,它将被附加到 GitGitGadget 发送的电子邮件中,位于三减号线和差异统计(diffstat)之间(提交后的效果请参阅 补充章节:单补丁更改)。 |
如果您感到满意,请提交您的拉取请求。
运行 CI 并准备发送
如果您是第一次使用 GitGitGadget(很可能如此,因为您正在阅读本教程),那么需要有人为您授权使用该工具。正如 GitGitGadget 文档中提到的,您只需要一个已经在使用该工具的人在您的 PR 上发表评论,内容为 /allow <用户名>。即使没有授权,GitGitGadget 也会自动通过 CI 运行您的 PR,但在有人允许您使用该工具之前,您将无法 /submit 您的更改。
|
注意
|
您通常可以通过以下方式在 GitGitGadget 上找到可以为您授权 /allow 的人:要么查看最近有人被授予 /allow 权限的拉取请求(搜索:is:pr is:open "/allow"),在这种情况下,作者和授予 /allow 权限的人现在都可以为您授权 /allow;要么在 Libera Chat 上的 #git-devel IRC 频道上进行咨询,附上您的拉取请求链接并请求某人为您授权 /allow。 |
如果 CI 失败,您可以使用 git rebase -i 更新您的更改并再次推送您的分支
$ git push -f remotename psuh
事实上,您应该继续以这种方式进行更改,直到您的补丁被合并到 next 分支为止。
根据评论进行更新
请跳到 回应评审意见,以获取有关如何回复您将在邮件列表中收到的评审评论的信息。
一旦您在收到所有评审评论后,再次将您的分支整理成您想要的样式,您就可以再次提交
$ git push -f remotename psuh
接下来,去查看您针对 GitGitGadget 的拉取请求;您应该看到 CI 已经再次启动。现在,在 CI 运行期间,正是您修改拉取请求线索顶部描述的好时机;它将再次用作封面信。您应该利用这个空间来描述自上一个版本以来发生了哪些变化,以便您的评审者对他们正在看的内容有所了解。当 CI 运行完毕后,您可以再次发表 /submit 评论——GitGitGadget 会自动在您的更改中添加 v2 标记。
使用 git send-email 发送补丁
如果您不想使用 GitGitGadget,您也可以使用 Git 本身来邮寄您的补丁。通过这种方式使用 Git 的一些好处包括对主题行的更细粒度控制(例如,能够在主题中使用 [RFC PATCH] 标记),以及能够给自己发送一封“试运行(dry run)”邮件,以在发送到邮件列表之前确保一切看起来都很好。
前提条件:设置 git send-email
send-email 的配置可能会根据您的操作系统和电子邮件提供商而有所不同,因此本教程中将不予涵盖,仅在此说明:在许多 Linux 发行版中,git-send-email 未与典型的 git 安装包一同打包。您可能需要单独安装这个额外的软件包;网上有许多资源可以帮助您完成此操作。您还需要确定正确配置它以使用您的 SMTP 服务器的方法;同样,由于此配置可能会根据您的系统和电子邮件设置而发生巨大变化,因此超出了本教程的讨论范围。
准备初始补丁集
使用 Git 发送电子邮件是一个分为两部分的过程;在准备电子邮件本身之前,您需要先准备好补丁。幸运的是,这非常简单
$ git format-patch --cover-letter -o psuh/ --base=auto psuh@{u}..psuh
-
--cover-letter选项告诉format-patch为您创建一个封面信模板。在准备好发送之前,您需要填写该模板——但目前,该模板将与您的其他补丁放在一起。 -
-opsuh/选项告诉format-patch将补丁文件放入一个目录中。这很有用,因为gitsend-email可以接受一个目录并从该目录中发送所有补丁。 -
--base=auto选项告诉该命令记录“基础提交(base commit)”,接收者应在该提交之上应用补丁系列。auto值将使format-patch自动计算基础提交,即远程跟踪分支的末端提交与指定修订范围的合并基础。 -
psuh@{u}..psuh选项告诉format-patch为您自psuh分支从上游派生(如果您遵循了“设置您的工作区”部分中的示例,上游即为origin/master)以来在其上创建的提交生成补丁。如果您已经在psuh分支上,您只需写@{u},这意味着“当前分支上自主其上游派生以来的提交”,这两者是一样的。
该命令将为每个提交生成一个补丁文件。运行之后,您可以使用您最喜欢的文本编辑器去查看每个补丁,确保一切看起来都正常;但是,不建议通过直接修改补丁文件来进行代码修复。更好的做法是使用 git rebase -i 以常规方式进行更改,或者添加一个新的提交,而不是去修改补丁。
|
注意
|
(可选)您还可以使用 --rfc 标志将您的补丁主题前缀设为 “[RFC PATCH]” 而不是 “[PATCH]”。RFC 代表“征求意见(request for comments)”,表示虽然您的代码尚未完全准备好提交,但您希望开始代码评审流程。当您的补丁是一项提案,但您不确定社区是否希望采用该方法解决问题时,也可以使用此方法——以进行某种设计评审。您可能还会在邮件列表中看到标记为 “WIP” 的补丁——这意味着它们尚未完成,但希望评审者看看目前已有的内容。您可以使用 --subject-prefix=WIP 来添加此标志。 |
检查并确保您的补丁和封面信模板存在于您指定的目录中——您就快准备好发送您的评审申请了!
准备电子邮件
由于您在调用 format-patch 时使用了 --cover-letter,您已经有了一个准备好的封面信模板。在您最喜欢的编辑器中打开它。
您应该会看到已经存在一些标头。检查您的 From: 标头是否正确。然后修改您的 Subject:(主题)(关于如何为您的补丁系列选择一个好标题,请参见上文)
Subject: [PATCH 0/7] Add the 'psuh' command
请确保您保留了 “[PATCH 0/X]” 部分;这是向 Git 社区表明此电子邮件是补丁系列开头的标志,许多评审者会针对此类标志过滤其电子邮件。
在调用 git send-email 添加封面信时,您需要添加一些额外的参数。
接下来您必须填写封面信的正文。同样,关于应包含哪些内容,请参见上文。
由 git format-patch --cover-letter 创建的模板包含一个差异统计(diffstat)。这能让评审者大致了解在评审您的主题分支时需要面对哪些内容。为样例实现中的 psuh 生成的 diffstat 如下所示
Documentation/git-psuh.adoc | 40 +++++++++++++++++++++ Makefile | 1 + builtin.h | 1 + builtin/psuh.c | 73 ++++++++++++++++++++++++++++++++++++++ git.c | 1 + t/t9999-psuh-tutorial.sh | 12 +++++++ 6 files changed, 128 insertions(+) create mode 100644 Documentation/git-psuh.adoc create mode 100644 builtin/psuh.c create mode 100755 t/t9999-psuh-tutorial.sh
该信件将包含用于生成补丁的 Git 版本。您可以保留该字符串不作改动。
发送电子邮件
此时,您应该有一个填满了您的补丁和一封封面信的 psuh/ 目录。是时候把它邮寄出去了!您可以像这样发送它
$ git send-email --to=target@example.com psuh/*.patch
|
注意
|
查看 git help send-email 以获取您可能认为有价值的其他一些选项,例如更改 Reply-to(回复至)地址或添加更多 CC(抄送)和 BCC(密送)行。 |
|
注意
|
如果您不确定要抄送给谁,运行 contrib/contacts/git-contacts 可以列出潜在的评审者。此外,您可以执行 git send-email --cc-cmd='perl contrib/contacts/git-contacts' feature/*.patch[1],以自动将该电子邮件列表传递给 send-email。 |
|
注意
|
当您发送真实的补丁时,它会发送到 git@vger.kernel.org——但请不要将本教程中的补丁集发送到真实的邮件列表中!目前,您可以将其发送给自己,以确保您了解其外观效果。 |
|
注意
|
发送补丁后,您可以通过访问 https://lore.kernel.org/git/ 来确认它们是否已到达邮件列表。使用搜索栏找到您的名字或您补丁的主题。如果它出现了,说明您的电子邮件已成功送达。 |
在您运行上面的命令后,对于即将发送的每个补丁,系统都会向您呈现一个交互式提示。这为您提供了最后一次编辑或放弃发送某些内容的机会(但请注意,不要通过这种方式编辑代码)。一旦您在这些提示下按下 y 或 a,您的电子邮件就会被发送出去!恭喜!
太棒了,现在社区会放下一切来评审您的修改。(开玩笑的——请耐心等待!)
发送 v2 版本
本节将重点介绍如何发送您补丁集的 v2 版本。要了解 v2 中应该包含哪些内容,请跳到 回应评审意见,以获取有关如何处理评审者评论的信息。
我们将为 v2 重新使用我们的 psuh 主题分支。在进行任何更改之前,我们将标记我们 v1 分支的末端,以便轻松引用
$ git checkout psuh $ git branch psuh-v1
使用 git rebase -i 根据评审者的意见调整提交,从而精炼您的补丁系列。一旦补丁系列准备好提交,请再次生成您的补丁,但要带有一些新的标志
$ git format-patch -v2 --cover-letter -o psuh/ --range-diff master..psuh-v1 master..
--range-diff master..psuh-v1 参数告诉 format-patch 在封面信中包含 psuh-v1 和 psuh 之间的范围差异(range-diff)(参见 git-range-diff[1])。这有助于让评审者了解您的 v1 和 v2 补丁之间的差异。
-v2 参数告诉 format-patch 将您的补丁作为版本 “2” 输出。例如,您可能会注意到您的 v2 补丁都被命名为类似于 v2-000n-my-commit-subject.patch。 -v2 还会通过将您的补丁前缀设为 “[PATCH v2]” 而不是 “[PATCH]” 来对其进行格式化,并且您的范围差异(range-diff)将以 “Range-diff against v1” 作为前言。
运行此命令后,format-patch 将把补丁输出到 psuh/ 目录中,与 v1 补丁放在一起。使用单个目录可以方便在校对 v2 补丁时参考旧的 v1 补丁,但您需要小心,只发送 v2 补丁。我们将使用诸如 psuh/v2-*.patch 之类的模式(而不是 psuh/*.patch,后者会同时匹配 v1 and v2 补丁)。
再次编辑您的封面信。如果有重大改动,现在是提及上一个版本与现在有何不同的大好时机。您的第二封封面信不需要完全相同的正文;重点向评审者解释您所做的、可能不那么显而易见的更改。
您还需要找到您上一封封面信的 Message-ID。您可以在发送第一个系列时从 git send-email 的输出中记录它,也可以在邮件列表上查找。在存档中找到您的封面信,点击它,然后点击 “permalink”(永久链接)或 “raw”(原始格式)以显示 Message-ID 标头。它应该匹配
Message-ID: <foo.12345.author@example.com>
您的 Message-ID 是 <foo.12345.author@example.com>。该示例也将在下文中使用;请确保将其替换为您的**上一封封面信**的正确 Message-ID——也就是说,如果您要发送 v2,请使用来自 v1 的 Message-ID;如果您要发送 v3,请使用来自 v2 的 Message-ID。
当您查看电子邮件时,您还应该注意谁被抄送(CC)了,因为在邮件列表中,将所有抄送人员保留在同一线索中是常见做法。您可以直接在您的封面信标头中(在主题行之前)添加像这样的一行抄送行
CC: author@example.com, Othe R <other@example.com>
现在再次发送电子邮件,密切注意您传递给该命令的是哪些邮件
$ git send-email --to=target@example.com --in-reply-to="<foo.12345.author@example.com>" psuh/v2-*.patch
补充章节:单补丁更改
在某些情况下,您的微小更改可能仅包含一个补丁。当这种情况发生时,您只需要发送一封电子邮件。您的提交说明应该已经很有意义,并从高层次解释了您补丁的目的(正在发生什么以及为什么),但如果您需要提供更多上下文信息,您可以在补丁中的 --- 下方进行。以如下示例为例,该示例是通过对单个提交使用 git format-patch 生成的,然后进行了编辑,以在 --- 和 diffstat 之间添加内容。
From 1345bbb3f7ac74abde040c12e737204689a72723 Mon Sep 17 00:00:00 2001 From: A U Thor <author@example.com> Date: Thu, 18 Apr 2019 15:11:02 -0700 Subject: [PATCH] README: change the grammar I think it looks better this way. This part of the commit message will end up in the commit-log. Signed-off-by: A U Thor <author@example.com> --- Let's have a wild discussion about grammar on the mailing list. This part of my email will never end up in the commit log. Here is where I can add additional context to the mailing list about my intent, outside of the context of the commit log. This section was added after `git format-patch` was run, by editing the patch file in a text editor. README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 88f126184c..38da593a60 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Git - fast, scalable, distributed revision control system ========================================================= -Git is a fast, scalable, distributed revision control system with an +Git is a fast, scalable, and distributed revision control system with an unusually rich command set that provides both high-level operations and full access to internals. -- 2.21.0.392.gf8f6787159e-goog
我的补丁已发送——接下来该做什么?
在发送更新版本之前,请给评审者足够的时间来处理您的初始补丁。也就是说,要克制住立即发送新版本的冲动,因为其他人可能已经开始评审您的初始版本了。
在等待评审意见时,您可能会发现初始补丁中的错误,或者意识到有另一种更好实现补丁目标的方法。在这种情况下,您可以按照以下方式将您的发现传达给其他评审者:
-
如果您发现的错误很小,请以评审者的身份给您的补丁发送一封回复,并提到您将在更新版本中修复这些错误。
-
另一方面,如果您认为自己想要做如此彻底的改变,以至于对初始补丁的评审将是浪费时间(对所有相关人员而言),请立即撤回该补丁,并在回复中说明,例如:“我正在研究一种好得多的方法,因此请忽略此补丁并等待更新版本。”
当然,如果您过早发送了未润色的初始补丁,上述方法是不错的实践。但更好的方法当然是从一开始就避免过早发送补丁。
请顾及评审者检查您补丁的每个新版本所需的时间。比起立即看到初始版本(接着在两天内收到好几个“哎呀,比起上一个,我更喜欢这版”的补丁),评审者强烈希望两天后能收到一个经过润色的单一版本,而那版错误较少的版本是他们唯一需要评审的版本。
回应评审意见
几天后,您有望收到关于您补丁集的一些意见。呜呼!现在您可以重新回去工作了。
回复每条评论是一种礼貌行为,您可以通知评审者您已做出建议的修改、认为原版更好,或者是该评论激发了您以一种优于原版和建议修改的新方法来处理。这样,评审者就不需要去检查您的 v2 版本来判断您是否采纳了他们的意见。
评审者可能会询问您在补丁集里写了什么,不管是在提议的提交日志说明中还是在更改本身中。您应该在您的回复邮件中回答这些问题,但评审者之所以提出这些问题来理解您想要表达的意思,往往是因为您的补丁集需要进一步澄清才能被理解。
不要仅仅满足于在回复中解答他们的问题并听他们说他们现在明白您想说什么。请更新您的补丁,以澄清评审者感到困惑的地方,并准备您的 v2;您用来解释您的 v1 以回答评审者问题的言词可能是很有用的素材。您的目标是使您的 v2 足够清晰,从而使您无需向下一个阅读它的人做出相同的解释。
如果您打算反驳某条意见,请保持礼貌并解释为什么您觉得您原先的设计更好;要做好准备评审者可能仍会不同意您的看法,而社区的其他成员可能会偏向某一方。正如所有的代码评审一样,对采用与您最初计划不同的方式做事保持开放心态至关重要;其他评审者对该项目有着与您不同的视角,并且可能会想到您未曾考虑到的合理副作用。如果您不确定为什么要建议某项更改,或者评审者要求您做什么,随时可以要求对方进行澄清。
确保您的电子邮件客户端具有纯文本电子邮件模式,并且已将其开启;Git 邮件列表会拒收 HTML 格式的电子邮件。还请遵守 维护者笔记(Maintainer’s Note) 中概述的邮件列表礼仪,这与大多数开源社区中围绕底部回复(bottom-posting)和行内回复(inline)的礼仪规则相似。
当您对代码进行更改时,如果您使用 git rebase -i(交互式变基),其结果是最干净的——即由此产生的提交最易于查看。看一下 O’Reilly 的这篇概述。大致思路是修改每一个需要更改的提交;这样,您无需在 v2 中保留一个有错误的补丁 A、一个在 v1 中完好且无需上游评审的补丁 B,以及一个用于在 v2 中修复补丁 A 的补丁 C,而是可以直接发布包含正确补丁 A 和正确补丁 B 的 v2。这是在修改历史,但由于这是您尚未与任何人分享的本地历史,因此目前是没问题的!(稍后,这样做可能就不合常理了;请查看本节下方的章节以获取一些背景信息。)
评审通过后
Git 项目有四个集成分支:seen、next、master 和 maint。在您的更改仍在评审过程中时,维护者会相当早地将其放入 seen 分支;此后,当它准备好进行更广泛的测试时,它将被合并到 next 分支中。许多空间早期测试者会使用 next 并可能报告问题。最终,next 中的更改会进入通常被认为是稳定版的 master 分支。最后,当发布新版本时,maint 分支将被用作错误修复(bugfix)的基础分支。正如本文档开头所提到的,您可以阅读 Documents/SubmittingPatches 以了解有关各种集成分支使用的更多信息。
回到现在:您的代码受到了上游评审者的称赞。它很完美。它已准备好被采纳。您不需要做任何其他事情;维护者会将您的主题分支合并到 next 中,一切都很美好。
然而,如果您在此之后发现它并非如此完美,您可能需要根据您在流程中所处的阶段采取一些特殊步骤。
如果维护者在 “What’s cooking in git.git” 电子邮件中宣布您的主题已被标记为准备并入 next——也就是说,他们计划将其合并到 next 但尚未合并——您应该发送一封电子邮件,请求维护者多等一会儿:“我已经发送了我系列的 v4 版本,并且您将其标记为了准备合并到 next,但我需要修改这儿和那儿——请在合并之前等待 v5 版本。”
如果主题已经合并到了 next,那么不应该使用 git rebase -i 来修改您的补丁,而是应该以增量方式进行进一步修改——即通过另一个提交,基于维护者主题分支的顶端,详见 https://github.com/gitster/git。您的工作仍处于同一主题中,但现在是增量的,而不是对主题分支进行大规模的重写。
维护者 GitHub 上的主题分支在 GitGitGadget 中也有镜像,因此如果您是通过这种方式发送评审申请的,您应该确保针对相应的 GitGitGadget/Git 分支开启您的 PR。
如果您正在使用 git send-email,您可以像以前一样使用它,但您应该从 <topic>..<mybranch> 生成 diff,并基于 <topic> 而不是 master 展开工作。