拉取请求的生命周期¶
简介¶
CPython 使用基于拉取请求的工作流。这意味着你在 Git 中创建一个分支,进行更改,将这些更改推送到 GitHub 上的分支 (origin
),然后针对官方 CPython 存储库 (upstream
) 创建一个拉取请求。
快速指南¶
清晰的沟通是为任何项目做出贡献的关键,尤其是像 CPython 这样的开源项目。
以下是有关如何为 CPython 做出贡献的快速概述
处理更改(例如修复错误或添加新功能)
运行测试和
make patchcheck
在 GitHub 上创建拉取请求以合并来自你的分支的分支
确保拉取请求上的持续集成检查为绿色(即成功)
查看并解决拉取请求上的评论
当你的更改合并后,你可以删除 PR 分支
庆祝为 CPython 做出贡献! :)
注意
为了保持提交历史记录的完整性,请避免压缩或修改历史记录,然后强制推送到 PR。审阅者通常希望查看各个提交。
分步指南¶
你应该已经设置了你的系统、获取了源代码并构建了 Python。
从您的
上游
存储库更新数据git fetch upstream
从上游存储库中的
main
分支在您的本地克隆中创建一个新分支git checkout -b <branch-name> upstream/main
注意
几乎所有对 Python 的更改(包括错误修复)都应首先针对
main
分支进行。有关更多详细信息,请参阅 此处。对代码进行更改,并使用
git status
和git diff
查看它们。(详细了解 创建良好的 PR)
确保更改正常,并且不会导致任何测试失败
make patchcheck ./python -m test
(详细了解 patchcheck 和 运行和编写测试)
对更改感到满意后,添加文件并提交它们
git add <filenames> git commit -m '<message>'
(详细了解 创建良好的提交)
如果您的代码没有正确地进行 linted,pre-commit 将使用错误消息阻止提交,例如
Doc/library/stdtypes.rst:5718: No newline at end of file. (missing-final-newline)
修复所有 linting 错误后,您可以将您的工作推送到您的 GitHub 分支
git push origin <branch-name>
最后进入
https://github.com/<your-username>/cpython
:您将看到一个包含您刚推送的分支的框和一个绿色的按钮,允许您针对官方 CPython 存储库创建拉取请求。当人们开始添加审阅评论时,您可以通过切换到您的分支、进行更多更改、提交它们并将其推送到自动更新您的 PR 来解决它们
git switch <branch-name> # make changes and run tests git add <filenames> git commit -m '<message>' git push origin <branch-name>
如果审阅您的 PR 的核心开发人员将一个或多个提交推送到您的 PR 分支,那么在签出您的分支并在编辑之前,运行
git pull origin <branch-name> # pull = fetch + merge
如果您已进行尚未推送到您的分支的本地更改,并且存在合并冲突,Git 将警告您并进入冲突解决模式。请参阅下面的 解决合并冲突。
如果时间流逝并且与主分支存在合并冲突,GitHub 将显示一个警告,您可能需要解决此问题。在本地解决冲突时,合并来自主分支的更改
git switch <branch-name> git pull upstream main # pull = fetch + merge # resolve conflicts: see "Resolving Merge Conflicts" below git push origin <branch-name>
您的 PR 被接受并合并后,您可以 删除分支
git branch -D <branch-name> # delete local branch git push origin -d <branch-name> # delete remote branch
解决合并冲突¶
从不同的分支(或不同存储库上的分支变体)合并更改时,这两个分支可能包含对一个或多个文件的不可兼容更改。这些称为“合并冲突”,需要手动解决,如下所示
检查哪些文件有合并冲突
git status
编辑受影响的文件并将它们调整到预期的最终状态。确保删除 Git 插入的特殊“冲突标记”。
提交受影响的文件
git add <filenames> git merge --continue
运行最终命令时,Git 可能会打开一个编辑器来编写提交消息。通常可以保持原样并关闭编辑器。
请参阅 合并命令的文档,以获得详细的技术说明。
创建良好的 PR¶
在创建拉取请求以提交时,您应该做一些事情来帮助确保您的拉取请求被接受。
针对正确的 Python 版本进行更改。一般来说,所有更改首先针对
main
分支进行。这包括错误修复。在更改在那里合并后,它将 回传 到较旧的 维护版本。这样,我们确保处理所有受影响的版本。因此,仅在特定情况下才基于维护分支直接进行新更改,例如,当该更改不适用于main
或该更改需要与main
相比在较旧的 Python 版本中采用不同的方法时。确保遵循 Python 的风格指南。对于 Python 代码,您应遵循 PEP 8,对于 C 代码,您应遵循 PEP 7。如果您有一两个差异,这些差异可以由合并您的拉取请求的核心开发者修复。但如果您对风格指南有系统性的偏差,您的拉取请求将被搁置,直到您修复格式问题。
注意
仅包含代码格式更改的拉取请求通常会被拒绝。另一方面,欢迎修复文档和文档字符串中的错别字和语法错误。
注意向后兼容性注意事项。虽然最终处理您的拉取请求的核心开发者将对某项内容是否可接受做出最终决定,但及早考虑向后兼容性将有助于防止您的拉取请求因这些理由而被拒绝。设身处地地想想,您的代码将因拉取请求引入的更改而中断。任何更改都很有可能中断某人的代码,因此您需要有充分的理由进行更改,因为您将强制某人更新其代码。(这显然不适用于新类或函数;新参数应为可选参数,并具有保持现有行为的默认值。)如果您有疑问,请查看 PEP 387 或 讨论 与经验丰富的开发者讨论该问题。
确保您有适当的测试来验证您的拉取请求按预期工作。没有适当的测试,拉取请求将不被接受!
确保所有测试都通过。由于您的更改,整个测试套件需要 运行 且无故障。仅运行似乎受您的更改影响的任何测试是不够的,因为在您的更改与解释器的其他部分之间可能存在您不知道的干扰。
应包括适当的 文档 添加/更改。
patchcheck
¶
patchcheck
是一个简单的自动化补丁清单,指导开发者完成常见的补丁生成检查。要运行 patchcheck
在 Unix(包括 macOS)上
make patchcheck
在 Windows(在任何成功的构建之后)上
.\python.bat Tools\patchcheck\patchcheck.py
自动化补丁清单运行
Python 文件中是否存在任何空格问题?(使用
Tools/patchcheck/reindent.py
)C 文件中是否存在任何空格问题?
文档中是否存在任何空格问题?
文档是否已更新?
测试套件是否已更新?
Misc/ACKS
是否已更新?如果需要,
configure
是否已重新生成?如果需要,
pyconfig.h.in
是否已重新生成?
自动化补丁检查实际上并不能回答所有这些问题。除了空格检查之外,该工具还可以帮助记忆构成完整补丁的各种元素。
进行良好的提交¶
每个功能或缺陷修复都应通过一个拉取请求来解决,并且对于每个拉取请求可能有多个提交。具体来说
不要在同一个提交中修复多个问题(当然,如果一个代码更改修复了所有问题除外)。
不要在与某些功能/缺陷修复相同的提交中对不相关的代码进行外观更改。
提交消息应遵循以下结构
Make the spam module more spammy
The spam module sporadically came up short on spam. This change
raises the amount of spam in the module by making it more spammy.
第一行或句子旨在对提交的目的进行简洁、直截了当的解释。强烈建议使用命令式(如上例中所示),而不是“垃圾邮件模块现在变得更加垃圾”之类的描述性形式。使用 git log --oneline
查看现有的标题行。此外,第一行不应以句号结尾。
如果这不足以详细说明提交,则可以添加一个或多个新段落来详细解释发生了什么(详细信息应足够好,以使阅读提交消息的核心开发人员了解更改的理由)。
查看 Git 入门训练营,了解合并拉取请求时提交消息应如何显示的进一步说明。
注意
如何撰写 Git 提交消息 是一篇描述如何撰写良好提交消息的好文章。
许可¶
要接受您的更改,我们必须得到您正式批准,以便在 PSF 许可证下分发您的作品。因此,您需要签署一份 贡献者协议,允许 Python 软件基金会 将您的代码授权用于 Python(您保留版权)。
注意
您只需签署此文件一次,它将适用于您对 Python 的所有进一步贡献。
以下是签署 CLA 所需的步骤
创建更改并将其作为拉取请求提交。
当
cpython-cla-bot
在您的拉取请求中评论说提交作者需要签署贡献者许可协议时,请单击评论中的按钮进行签署。通过 GitHub 登录即可。该过程是自动的。签署后,
cpython-cla-bot
的评论将更新,以表明“所有提交作者都已签署贡献者许可协议”。
提交¶
一旦您对自己的工作感到满意,您就会希望将您的更改提交到您的分支。通常,您可以运行 git commit -a
,它将提交所有内容。您始终可以运行 git status
来查看有哪些未完成的更改。
当您的所有更改都已提交(即 git status
没有列出任何内容)时,您将需要将您的分支推送到您的 fork
git push origin <branch name>
这会将您的更改提交到 GitHub。
现在您要从您的 fork 创建一个 pull request。如果这是对问题跟踪器上一个已存在问题的 pull request,请务必在 pull request 标题中使用gh-NNNNN:
前缀和在描述中使用#NNNNN
来引用问题编号。
如果这是针对未报告问题的 pull request(假设您已针对问题跟踪器上的已存在问题执行搜索),请创建一个新问题并在 pull request 中引用它。请尽可能填写尽可能多的相关详细信息,以防止审阅者因信息不足而不得不延迟审阅您的 pull request。
如果此问题非常简单,无需跟踪 pull request 试图解决的问题的任何讨论(例如,修复拼写错误),则需要由具有提交访问权限的人员向 pull request 添加“跳过问题”标签。
您的 pull request 可能涉及多次提交,这是为了解决代码审阅评论。请保持 pull request 中的提交历史记录完整,不要压缩、修改或任何需要强制推送到 GitHub 的操作。详细的提交历史记录允许审阅者查看一个提交到另一个提交的差异,以便他们可以轻松验证他们的评论是否已得到解决。合并 pull request 时,将压缩提交。
将现有的补丁从 b.p.o 转换为 GitHub¶
当问题跟踪器中存在一个补丁,该补丁应转换为 GitHub pull request 时,请首先要求原始补丁作者准备他们自己的 pull request。如果作者在一周后没有回复,则其他贡献者可以根据现有补丁准备 pull request。在这种情况下,双方都应签署CLA。在根据他人的补丁创建 pull request 时,通过向 pull request 描述和提交消息中添加“Co-authored-by: 作者姓名 <email_address> .”来归因于原始补丁作者。请参阅GitHub 文章,了解如何正确添加共同作者信息。
另请参阅将补丁应用到 Git。
审阅¶
首先,请耐心等待!提交 pull request 的人比能够审阅您 pull request 的人多得多。要让您的 pull request 得到审阅,需要审阅者有空闲时间和动力来查看您的 pull request(我们无法强迫任何人审阅 pull request,也没有人受雇于查看 pull request)。如果您的 pull request 在一个月后未收到审阅者的任何通知(即未发表任何评论),请首先在问题跟踪器上“ping”该问题,以提醒订阅者 pull request 需要审阅。如果您在 ping 问题后的一周内没有收到回复,则可以在核心开发讨论类别上发帖,要求某人审阅您的 pull request。
当有人设法抽出时间查看你的拉取请求时,他们很可能会对如何改进它发表评论(别担心,即使是 Python 的核心开发人员也会收到要求他们更改的拉取请求)。然后,你应该更新你的拉取请求以解决这些评论,并且审查过程将持续进行,直到出现令人满意的解决方案。
如何审查拉取请求¶
Python 开发过程中的一个瓶颈是缺乏代码审查。如果你浏览错误跟踪器,你会看到许多问题都有修复,但无法合并到主源代码存储库中,因为没有人审查提议的解决方案。审查拉取请求可能与提供拉取请求一样具有信息性,并且它将允许你对其他开发人员的工作提出建设性的评论。本指南提供了一个提交代码审查的清单。一个常见的误解是,为了有用,代码审查必须是完美的。事实并非如此!仅仅测试拉取请求和/或使用代码并留下拉取请求或问题跟踪器中的评论就很有帮助。
如果你还没有这样做,请按照设置指南获取 CPython 存储库的副本,构建它并运行测试。
检查错误跟踪器以查看重现该问题需要采取哪些步骤,并确认你可以在 Python REPL(交互式 shell 提示符)的版本中重现该问题,你可以通过在存储库中执行 ./python 来启动它。
签出并应用拉取请求(请参阅说明下载其他人的补丁)
如果更改影响任何 C 文件,请再次运行构建。
启动 Python REPL(交互式 shell 提示符)并检查你是否可以重现该问题。现在拉取请求已应用,该问题应该已得到修复(理论上,但确实会发生错误!好的审查旨在在代码合并到 Python 存储库之前捕获这些错误)。你还应该尝试查看修复作者可能错过的此问题或相关问题中的任何特殊情况。
如果你有时间,请运行整个测试套件。如果你时间紧迫,请运行应用更改的模块的测试。但是,请注意,如果你建议拉取请求为“合并就绪”,你应该始终确保整个测试套件通过。
在 GitHub 上留下拉取请求审查¶
当你审查拉取请求时,你应该提供审查过程的其他详细信息和背景。
不要简单地“批准”拉取请求,请留下评论。例如
如果你测试了 PR,请报告结果以及测试的系统和版本,例如“Windows 10”、“Ubuntu 16.4”或“Mac High Sierra”。
如果你要求更改,请尝试建议如何更改。
评论拉取请求中“好”的内容,而不仅仅是“坏”的内容。这样做将使 PR 作者更容易在你的评论中找到好的内容。
查看当前 PR 中 CI 的任何故障。请参阅下面的“保持 CI 绿色”,了解你可以采取哪些简单措施来帮助推进 PR。
驳回另一位核心开发人员的审查¶
如果核心开发人员确认已进行请求的更改,则可以驳回另一位核心开发人员的审查。当核心开发人员将 PR 分配给自己时,这表明他们正在积极关注 PR,并且不应驳回他们的审查。
保持持续集成绿色¶
我们的变更管理工作流通常不允许合并带有故障的 PR。因此,如果你在 PR 上看到 CI 故障,请查看其原因。
通常,故障将直接与当前 PR 中的变更相关。如果你碰巧对故障有所了解,请在审查评论中告知作者。CI 运行有时会生成数千行输出。即使像找到回溯并将其放入评论中这样简单的事情也会对 PR 作者有所帮助。
如果故障看起来与你正在查看的变更无关,请检查它是否也不存在于 发布状态 Buildbot 仪表板中。如果是这样,这意味着故障是在之前的变更中引入的。使用 Buildbot 的 UI,你可以找到引入问题的 PR,并评论它会影响其他 PR。
如果你仍然看不到故障的来源,请在已执行检查列表旁边检查“此分支与基础分支不同步”标志。单击此消息旁边的“更新分支”将合并基础分支中的最新变更到 PR 中。
如果这仍然无法解决 PR 上的故障,你可以尝试重新运行该特定故障检查。转到红色的 GitHub Action 作业,单击右上角的“重新运行作业”按钮,然后选择“重新运行失败的作业”。只有当所有其他作业完成运行后,此按钮才会出现。
重新运行失败的作业不应该是你的第一本能,但有时很有帮助,因为分布式系统可能会出现间歇性故障,并且我们的一些单元测试对虚拟机过载很敏感。如果你发现了这种不稳定的行为,请在 问题跟踪器 中查找描述此特定不稳定性的问题。如果你找不到,请创建一个新问题。
提交/拒绝¶
一旦你的拉取请求达到可接受的状态(因此被认为是“已接受”),它将被合并或拒绝。如果它被拒绝,请不要介意!无论你的拉取请求是否被合并,你的工作仍然受到赞赏。平衡什么可以和不可以进入 Python 是很棘手的,我们根本无法接受每个人的贡献。
但如果你的拉取请求被合并,它将进入 Python 的 VCS,以便在 Python 的下一个功能版本中发布。如果执行合并的核心开发人员认为有必要,它也可能作为错误修复回传到 Python 的旧版本。
鸣谢¶
非平凡的贡献会在 Misc/ACKS
文件(以及最常见的是在贡献的新闻条目中)中得到认可。你可能会被要求代表接受你的拉取请求的核心开发人员进行这些编辑。