使用 Git 和 GitHub 工作

这一部分解释了社区如何通过拉取请求向 Django 贡献代码。如果你对 mergers 如何处理它们感兴趣,请参阅 提交代码

接下来,我们将展示如何创建一个包含 Trac 问题 #xxxxx 的更改的 GitHub 拉取请求。通过创建一个完全准备好的拉取请求,你将会让审阅者的工作更容易,这意味着你的工作更有可能被合并到 Django 中。

您也可以将传统的补丁程序上传到 Trac ,但对于评论来说不太实用。

安装 Git

Django 使用 Git 进行源代码控制。你可以从 这里下载 Git,但通常更容易使用你的操作系统的包管理器进行安装。

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

在安装 Git 后,你首先要做的事情是设置你的姓名和电子邮件地址:

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

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

设置本地仓库

当你创建了你的 GitHub 帐户,使用昵称 “GitHub_nick”,并且 fork 了 Django 的存储库,创建你的 fork 的本地副本:

  1. git clone https://github.com/GitHub_nick/django.git

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

  1. cd django

在 Git 中,你的 Github 仓库会被称做“origin”。

你还应该将 django/django 设置为一个 “upstream” 远程仓库(也就是告诉 Git 参照 Django 的存储库作为你 fork 的源头):

  1. git remote add upstream https://github.com/django/django.git
  2. git fetch upstream

你可以以类似的方式添加其他远程仓库,例如:

  1. git remote add akaariai https://github.com/akaariai/django.git

在工单上工作

在处理一个问题时,为这项工作创建一个新的分支,并以 upstream/main 为基础进行工作:

  1. git checkout -b ticket_xxxxx upstream/main

-b 参数在本地为您创建一个新分支。 即使是最小的事情,也不要犹豫创建新分支——这就是它们的用途。

如果你正在为 1.4 分支上的修复工作,你会执行如下操作:

  1. git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x

假设工作是在 ticket_xxxxx 分支上进行的。进行一些更改并提交它们:

  1. git commit

在编写提交消息时,遵循 提交消息指南 以便让合并者的工作更容易。如果你不太擅长英语,至少尽量准确描述提交的操作。

如果需要在你的分支上进行额外的工作,根据需要进行多次提交:

  1. git commit -m 'Added two more tests for edge cases'

发布工作成果

你可以通过运行以下命令将你的工作发布到 GitHub:

  1. git push origin ticket_xxxxx

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

如果你正在处理一个 Trac 问题,你应该在问题中提到你的工作可以在你的 GitHub 存储库的 ticket_xxxxx 分支中找到。包括一个指向你的分支的链接。

请注意,在Git中,上述分支称为“主题分支”。 您可以自由地重写该分支的历史记录,例如,使用 git rebase 变更基本。 其他人不应在这样的分支上进行工作,因为当您编辑提交时,他们的副本会损坏。

还有”公共分支”。其他人应该 fork 这些分支,因此这些分支的历史永远不应该更改。django/django 存储库中的 “main” 和 “stable/A.B.x” 分支就是很好的公共分支的示例。

当您准备将工作成果并入Django时,应在GitHub上创建一个pull请求。好的拉取请求要求:

  • 按照:doc:coding style <coding-style> ,每个提交都进行一次逻辑更改,
  • 每次提交的格式正确的消息:摘要行,其后以72个字符包装的段落——有关详细信息,请参见 committing guidelines
  • 如果需要,带有文档和测试——实际上一直需要测试,除了文档更改外。

测试套件必须通过,并且文档的构建必须没有警告。

一旦你创建了拉取请求,你应该在相关的 Trac 问题中添加一个评论,解释你所做的事情。特别是,你应该注明你运行测试的环境,例如:”在 SQLite 和 MySQL 下都通过了所有测试”。

GitHub 上的拉取请求只有两种状态:打开和关闭。将处理你的拉取请求的合并者只有两个选项:合并它或关闭它。因此,在代码准备好合并或足够接近以便合并者可以自己完成之前,创建拉取请求并没有太大的用处。

分支变基

在上面的示例中,你创建了两个提交,一个是 “Fixed ticket_xxxxx” 提交,另一个是 “Added two more tests” 提交。

我们不想在您的代码库中拥有您工作过程的全部历史记录。您的提交“添加了两个以上的测试”将毫无助益。相反,我们只希望一次提交包含您的所有工作。

要重塑你的分支历史,你可以使用交互式变基将多个提交合并成一个:

  1. git rebase -i HEAD~2

上面的 HEAD~2 是最近两次提交的简写。 上面的命令将打开一个编辑器,显示两个提交,前缀为 “pick” 。

将第二行的 “pick” 更改为 “squash”。这将保留第一个提交,并将第二个提交合并到第一个提交中。保存并退出编辑器。然后会打开第二个编辑器窗口,以便你可以修改包含两个步骤的提交消息。

你也可以在变基中使用 “edit” 选项。这样你可以修改单个提交,例如修复文档字符串中的拼写错误:

  1. git rebase -i HEAD~3
  2. # Choose edit, pick, pick for the commits
  3. # Now you are able to rework the commit (use git add normally to add changes)
  4. # When finished, commit work with "--amend" and continue
  5. git commit --amend
  6. # Reword the commit message if needed
  7. git rebase --continue
  8. # The second and third commits should be applied.

如果你的主题分支已经在 GitHub 上发布,例如,如果你正在进行小的更改以考虑审查意见,你将需要强制推送这些更改:

  1. git push -f origin ticket_xxxxx

请注意,这将重写 ticket_xxxxx 的历史 - 如果你在 GitHub 上操作之前和之后检查提交哈希值,你会注意到提交哈希值不再匹配。这是可以接受的,因为这个分支是一个主题分支,没有人应该以它为基础进行工作。

在上游发生变化之后

当上游(django/django)发生变化时,你应该重新基于你的工作。要做到这一点,使用以下命令:

  1. git fetch upstream
  2. git rebase upstream/main

工作会自动使用你 fork 的分支进行重新基于,在示例中使用的是 upstream/main

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

如果出现合并冲突,你需要解决它们,然后使用 git rebase --continue。在任何时候,你都可以使用 git rebase --abort 返回到原始状态。

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

这样做的原因是,通过重新定基,您的提交将始终在上游工作的*基础*上,而不是与上游所做的更改*混合在一起*。这样,您的分支将只包含与其主题相关的提交,这使得压缩更加容易。

审阅之后

在审核者未要求更改的情况下,将任何不重要的代码放入内核是很不正常的。 在这种情况下,通常最好将更改添加为对工作的一次增量提交。 这使审阅者可以轻松地检查您所做的更改。

在这种情况下,按照审阅者要求进行更改。根据需要进行多次提交。在发布更改之前,重新基于你的工作。如果你添加了两个提交,你可以运行以下命令:

  1. git rebase -i HEAD~2

将第二个提交合并到第一个提交中。编写一个类似以下的提交消息:

  1. Made changes asked in review by <reviewer>
  2. - Fixed whitespace errors in foobar
  3. - Reworded the docstring of bar()

最后,将你的工作推送回你的 GitHub 存储库。由于在重新基于过程中没有触及公共提交,你应该不需要强制推送:

  1. git push origin ticket_xxxxx

您的拉取请求现在也应该包含新的提交。

请注意,合并者在提交代码时很可能会将审阅提交合并到之前的提交中。

工作在一个补丁上

开发者可以通过审查补丁的方式之一来为 Django 做出贡献。这些补丁通常会作为 GitHub 上的拉取请求存在,可以轻松地集成到你的本地存储库中:

  1. git checkout -b pull_xxxxx upstream/main
  2. curl -L https://github.com/django/django/pull/xxxxx.patch | git am

这将创建一个新的分支,然后将拉取请求中的更改应用到该分支上。在这一点上,你可以运行测试或进行其他必要的操作来调查补丁的质量。

有关与拉取请求一起工作的更多详细信息,请参阅 合并者指南

概览

  • 如果可以,请在GitHub上工作。
  • 通过链接到您的GitHub分支来宣布您在Trac工单上的工作。
  • 准备就绪后,请提出拉取请求。
  • 使您的拉取请求尽可能地好。
  • 在对您的工作进行修复时,请使用 git rebase -i 压缩提交。
  • 当上游发生变化时,请执行 git fetch upstream; git rebase