本节介绍社区如何通过pull请求为Django贡献代码。如果您对核心开发人员如何处理它们感兴趣,请参阅Committing code。
下面,我们将展示如何创建一个包含Trac票据#xxxxx的更改的GitHub pull请求。通过创建一个完全准备的pull请求,您将使审阅者的工作更容易,这意味着您的工作更有可能被合并到Django。
你也可以上传一个传统的补丁到Trac,但它不太实用的评论。
Django使用Git作为其源代码控制。您可以下载 Git,但通常使用操作系统的软件包管理器更容易。
Django的Git存储库托管在GitHub上,建议您也使用GitHub。
安装Git后,你应该做的第一件事是设置你的名字和电子邮件:
$ git config --global user.name "Your Real Name"
$ git config --global user.email "[email protected]"
请注意,user.name应该是您的真实姓名,而不是您的GitHub nick。GitHub应该知道您在user.email字段中使用的电子邮件,因为这将用于将您的提交与您的GitHub帐户相关联。
当你创建了你的GitHub帐户,使用缺口“github_nick”和分叉的Django的存储库,创建你的fork的本地副本:
git clone [email protected]:github_nick/django.git
这将创建一个新目录“django”,其中包含您的GitHub存储库的克隆。此页面上的其余git命令需要在克隆目录中运行,现在切换到它:
cd django
您的GitHub存储库将在Git中称为“origin”。
您还应该将django / django设置为“上游”远程(即,告诉git引用Django存储库是它的源代码):
git remote add upstream [email protected]:django/django.git
git fetch upstream
您可以类似地添加其他远程文件,例如:
git remote add akaariai [email protected]:akaariai/django.git
当在票证上工作创建一个新的分支的工作,并基于上游/主机上的工作:
git checkout -b ticket_xxxxx upstream/master
-b标志在本地为您创建一个新的分支。不要犹豫,为最小的事情创建新的分支 - 这就是他们在那里。
如果相反你正在1.4分支上修复,你会做:
git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x
假设工作在ticket_xxxxx分支上进行。进行一些更改并提交它们:
git commit
在编写提交消息时,请按照commit message guidelines来简化提交者的工作。如果你对英语不舒服,至少尝试描述提交是什么。
如果您需要在您的分支上执行其他操作,请按需提交:
git commit -m 'Added two more tests for edge cases'
你可以在GitHub上发布你的工作:
git push origin ticket_xxxxx
当你去你的GitHub页面,你会注意到一个新的分支已创建。
如果您正在使用Trac票,您应该在票证中提到您的工作可从您的github repo的分支ticket_xxxxx获得。包括指向您分支的链接。
注意,上述分支在Git中被称为“主题分支”。例如,您可以使用git rebase来自由重写此分支的历史记录。其他人不应该将他们的工作基于这样的分支,因为他们的克隆将在您编辑提交时损坏。
还有“公共分支”。这些是其他人应该分叉的分支,所以这些分支的历史不应该改变。公共分支的好例子是django / django存储库中的master和stable/A.B.x分支。
当你认为你的工作准备好进入Django时,你应该在GitHub上创建一个pull请求。良好的牵引请求意味着:
测试套件必须通过,文档必须构建而不出现警告。
一旦你创建了pull请求,你应该在相关的Trac票证中添加一条评论,解释你做了什么。特别是你应该注意运行测试的环境,例如:“所有测试通过SQLite和MySQL”。
在GitHub的pull请求只有两个状态:打开和关闭。提交者将处理你的pull请求只有两个选项:合并或关闭它。为此,在代码准备好合并之前,或者足够接近提交者自己完成它之前,提出pull请求是没有用的。
在上面的示例中,您创建了两个提交,“Fixed ticket_xxxxx”提交和“添加另外两个测试”提交。
我们不想在您的存储库中有整个工作过程的历史记录。你的承诺“增加了两个测试”将是无益的噪音。相反,我们宁愿只有一个包含所有工作的提交。
要重做您的分支的历史,您可以通过使用交互式rebase将提交压缩为一个:
git rebase -i HEAD~2
上面的HEAD〜2是两个最新提交的缩写。上面的命令将打开一个编辑器,显示两个提交,前面加上“pick”一词。
将第二行上的“选择”改为“挤压”。这将保持第一个提交,并将第二个提交压缩到第一个提交。保存并退出编辑器。第二个编辑器窗口应该打开,因此您可以为提交重新编写提交消息,因为它包括两个步骤。
您还可以在rebase中使用“编辑”选项。这样,您可以更改单个提交,例如修复docstring中的错误:
git rebase -i HEAD~3
# Choose edit, pick, pick for the commits
# Now you are able to rework the commit (use git add normally to add changes)
# When finished, commit work with "--amend" and continue
git commit --amend
# reword the commit message if needed
git rebase --continue
# The second and third commits should be applied.
如果您的主题分支已经在GitHub上发布,例如,如果您正在进行一些小的更改以考虑评论,您将需要强制推送更改:
git push -f origin ticket_xxxxx
注意,这将重写ticket_xxxxx的历史记录 - 如果你检查在GitHub操作之前和之后的提交哈希,你会注意到提交哈希不再匹配。这是可以接受的,因为分支只是一个主题分支,没有人应该根据它的工作。
当上游(django / django)已经改变,你应该rebase你的工作。为此,请使用:
git fetch upstream
git rebase
工作将使用您分支的分支自动重组,在示例中使用upstream / master。
rebase命令临时删除所有本地提交,应用上游提交,然后再次对工作应用本地提交。
如果存在合并冲突,您需要先解决它们,然后使用git rebase - 继续。在任何时候,您都可以使用git rebase - abort返回原始状态。
请注意,您想要在上游改变,而不是合并上游。
这样做的原因是,通过重基础,您的提交将总是在上游的工作之上,而不是与混合在上游的变化。这样,您的分支将仅包含与其主题相关的提交,这使得压缩更容易。
在审核人员要求更改的情况下,将任何不重要的代码量包含到核心中是不寻常的。在这种情况下,通常最好将更改作为一个增量提交添加到工作中。这允许审阅者容易地检查您做了什么改变。
在这种情况下,请进行审阅者所需的更改。根据需要经常提交。在发布更改之前,重命名您的工作。如果添加了两个提交,您将运行:
git rebase -i HEAD~2
将第二个提交放入第一个提交。写一个提交消息的行:
Made changes asked in review by <reviewer>
- Fixed whitespace errors in foobar
- Reworded the docstring of bar()
最后把你的工作推回到你的GitHub仓库。由于你在rebase期间没有触摸公共提交,你不需要强制push:
git push origin ticket_xxxxx
您的pull请求现在应该包含新的提交。
请注意,提交者可能会在提交代码时将审核提交压缩到之前的提交中。
开发人员可以为Django做出贡献的方法之一是查看补丁。这些补丁通常作为pull请求存在于GitHub上,并且可以轻松地集成到您的本地存储库:
git checkout -b pull_xxxxx upstream/master
curl https://github.com/django/django/pull/xxxxx.patch | git am
这将创建一个新的分支,然后将更改从拉请求应用到它。此时,您可以运行测试或执行任何其他操作来调查补丁的质量。
有关处理拉取请求的更多详细信息,请参阅guidelines for committers。
2015年5月13日