Working with Git and GitHub

本节介绍社区如何通过pull请求为Django贡献代码。 如果您对提交者如何处理它们感兴趣,请参阅Committing code

下面,我们将展示如何创建一个包含Trac票据#xxxxx的更改的GitHub pull请求。 通过创建一个完全准备好的拉动请求,您将使审阅者的工作更轻松,这意味着您的工作更有可能被合并到Django中。

你也可以上传一个传统的补丁到Trac,但它不太实用的评论。

Installing Git

Django使用Git作为其源代码控制。 您可以下载 Git,但通常使用操作系统的软件包管理器更容易。

Django的Git存储库托管在GitHub上,建议您也使用GitHub。

安装Git后,您应该首先设置您的姓名和电子邮件地址:

$ git config --global user.name "Your Real Name"
$ git config --global user.email "you@email.com"

请注意,user.name应该是您的真实姓名,而不是您的GitHub nick。 GitHub应该知道您在user.email字段中使用的电子邮件,因为这将用于将您的提交与您的GitHub帐户相关联。

Setting up local repository

创建您的GitHub帐户时,使用“GitHub_nick”和分叉Django的存储库创建一个本地的叉子副本:

git clone git@github.com:GitHub_nick/django.git

这将创建一个新目录“django”,其中包含您的GitHub存储库的克隆。 此页面上的其余git命令需要在克隆目录中运行,因此现在切换到它:

cd django

您的GitHub存储库将在Git中称为“origin”。

还应该设置django/django

git remote add upstream git@github.com:django/django.git
git fetch upstream

您可以类似地添加其他远程文件,例如:

git remote add akaariai git@github.com:akaariai/django.git

Working on a ticket

在工作票时,为工作创建一个新的分支,并且在上游/主机上工作:

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'

Publishing work

你可以在GitHub上发布你的工作:

git push origin ticket_xxxxx

当您访问GitHub页面时,您将注意到已经创建了一个新的分支。

如果您正在使用Trac机票,您应该在机票中提及您的工作可从您的GitHub repo的分支ticket_xxxxx中获得。 包括指向您分支的链接。

注意,上述分支在Git中被称为“主题分支”。 例如,您可以使用git rebase来自由重写此分支的历史记录。 其他人不应该将他们的工作基于这样的分支,因为他们的克隆将在您编辑提交时损坏。

还有“公共分支”。 这些是其他人应该分叉的分支,所以这些分支的历史不应该改变。 公共分支的良好示例是masterstable/A.B.x分支在django/django资源库中。

当你认为你的工作准备好进入Django时,你应该在GitHub上创建一个pull请求。 良好的牵引请求意味着:

  • coding style之后,在每个中提交一个逻辑更改,
  • 每个提交的格式正确的消息:汇总行,然后段落包裹在72个字符之后 - 有关更多详细信息,请参阅committing guidelines
  • 文档和测试,如果需要 - 实际上总是需要测试,除了文档更改。

测试套件必须通过,文档必须构建而不出现警告。

一旦你创建了pull请求,你应该在相关的Trac票证中添加一条评论,解释你做了什么。 特别是,您应该注意运行测试的环境,例如:“所有测试通过SQLite和MySQL”。

在GitHub的pull请求只有两个状态:打开和关闭。 提交者将处理你的pull请求只有两个选项:合并或关闭它。 为此,在代码准备好合并之前,或者足够接近提交者自己完成它之前,提出pull请求是没有用的。

Rebasing branches

在上面的示例中,您创建了两个提交“固定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操作之前和之后检查提交散列,您会注意到提交哈希不再匹配。 这是可以接受的,因为分支只是一个主题分支,没有人应该根据它的工作。

After upstream has changed

当上游(django/django)已更改时,您应该修改您的工作。 为此,请使用:

git fetch upstream
git rebase

在使用upstream/master的示例中,使用您分支的分支自动重新开始工作。

rebase命令临时删除所有本地提交,应用上游提交,然后再次对工作应用本地提交。

如果存在合并冲突,则需要解决它们,然后使用git rebase - 继续 在任何时候,您都可以使用git rebase - abort返回原始状态。

请注意,您想要在上游改变,而不是合并上游。

这样做的原因是,通过重基础,您的提交将总是上游的工作之上,而不是混合在上游的变化。 这样,您的分支将仅包含与其主题相关的提交,这使得压缩更容易。

After review

在审核人员要求更改的情况下,将任何不重要的代码量包含到核心中是不寻常的。 在这种情况下,通常最好将更改作为一个增量提交添加到工作中。 这允许审阅者容易地检查您做了什么改变。

在这种情况下,请进行审阅者所需的更改。 根据需要经常提交。 在发布更改之前,重命名您的工作。 如果添加了两个提交,您将运行:

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请求现在应该包含新的提交。

请注意,提交者可能会在提交代码时将审核提交压缩到之前的提交中。

Working on a patch

开发人员可以为Django做出贡献的方法之一是查看补丁。 这些补丁通常作为pull请求存在于GitHub上,并且可以轻松地集成到您的本地存储库:

git checkout -b pull_xxxxx upstream/master
curl https://github.com/django/django/pull/xxxxx.patch | git am

这将创建一个新的分支,然后将更改从拉请求应用到它。 此时,您可以运行测试或执行任何其他操作来调查补丁的质量。

有关处理拉取请求的更多详细信息,请参阅guidelines for committers

Summary

  • 如果可以的话,在GitHub上工作。
  • 通过链接到您的GitHub分支宣布您的工作在Trac票。
  • 当你有一些准备好,做一个拉请求。
  • 使你的请求尽可能好。
  • 在修正工作时,请使用git rebase -i来压缩提交。
  • 当上游发生变化时,请执行git fetch upstream; git rebase