章节 ▾ 第二版

6.3 GitHub - 维护项目

维护项目

现在我们已经很熟悉如何为一个项目做贡献了,让我们来看一下另一个方面:创建、维护和管理你自己的项目。

创建新仓库

让我们创建一个新的仓库来分享我们的项目代码。首先点击仪表板右侧的“New repository”按钮,或者从用户名旁边顶部工具栏中的+按钮,如“New repository”下拉菜单所示。

The “Your repositories” area
图 109. “Your repositories”区域
The “New repository” dropdown
图 110. “New repository”下拉菜单

这将带你到“new repository”表单

The “new repository” form
图 111. “new repository”表单

在这里你只需要提供一个项目名称;其余的字段都是可选的。现在,只需点击“Create Repository”按钮,砰!你就拥有了一个新的 GitHub 仓库,命名为<user>/<project_name>

由于你还没有任何代码,GitHub 将向你展示如何创建一个全新的 Git 仓库,或者连接一个现有的 Git 项目。我们不会在这里赘述;如果你需要复习,请查看Git 基础

现在你的项目已经托管在 GitHub 上了,你可以把 URL 分享给任何你想分享项目的人。 GitHub 上的每个项目都可以通过 HTTPS 以 https://github.com/<user>/<project_name> 的形式访问,也可以通过 SSH 以 git@github.com:<user>/<project_name> 的形式访问。 Git 可以从这些 URL 拉取(fetch)和推送(push),但访问权限会根据连接用户的凭据进行控制。

注意

对于公共项目,通常最好分享基于 HTTPS 的 URL,因为用户无需拥有 GitHub 帐户即可访问并克隆项目。 如果你向用户提供 SSH URL,他们必须拥有帐户并上传 SSH 密钥才能访问你的项目。 基于 HTTPS 的 URL 也与他们粘贴到浏览器中以查看该项目的 URL 完全相同。

添加协作者

如果你与其他人合作,并希望授予他们提交访问权限,你需要将他们添加为“协作者”。 如果 Ben、Jeff 和 Louise 都在 GitHub 上注册了帐户,并且你想授予他们对你的存储库的推送访问权限,你可以将他们添加到你的项目中。 这样做将授予他们“推送”访问权限,这意味着他们对项目和 Git 存储库都具有读写访问权限。

单击右侧边栏底部的“Settings”(设置)链接。

The repository settings link
图 112. 存储库设置链接

然后从左侧菜单中选择“Collaborators”(协作者)。 然后,只需在框中键入用户名,然后单击“Add collaborator”(添加协作者)。 你可以根据需要重复此操作多次,以授予你希望的每个人访问权限。 如果你需要撤销访问权限,只需单击其行右侧的“X”。

The repository collaborators box
图 113. 存储库协作者框

管理拉取请求

现在你已经有了一个包含一些代码的项目,甚至可能有一些也具有推送权限的协作者,让我们来了解一下当你自己收到拉取请求时该怎么办。

拉取请求可以来自你的存储库的一个 fork 中的分支,也可以来自同一存储库中的另一个分支。 唯一的区别是,fork 中的分支通常来自你无法向其分支推送并且他们也无法向你的分支推送的人员,而内部拉取请求通常双方都可以访问该分支。

在这些示例中,我们假设你是“tonychacon”并且你创建了一个名为“fade”的新 Arduino 代码项目。

电子邮件通知

有人对你的代码进行了更改并向你发送了一个拉取请求。 你应该会收到一封电子邮件通知你有关新的拉取请求,它应该看起来像 新的拉取请求的电子邮件通知

Email notification of a new Pull Request
图 114. 新的拉取请求的电子邮件通知

关于这封电子邮件,有几件事需要注意。 它会给你一个小的 diffstat —— 一个拉取请求中已更改的文件列表以及更改的程度。 它为你提供了一个指向 GitHub 上拉取请求的链接。 它还为你提供了一些可以从命令行使用的 URL。

如果你注意到包含 git pull <url> patch-1 的行,这是一种合并远程分支的简单方法,无需添加远程仓库。 我们在 检出远程分支 中快速介绍了这一点。 如果你愿意,你可以创建并切换到一个主题分支,然后运行此命令以合并拉取请求更改。

另一个有趣的 URL 是 .diff.patch URL,正如你可能猜到的,它们提供了拉取请求的统一差异和补丁版本。 从技术上讲,你可以使用如下内容合并拉取请求工作

$ curl https://github.com/tonychacon/fade/pull/1.patch | git am

协作处理拉取请求

正如我们在 GitHub 工作流 中介绍的那样,你现在可以与打开拉取请求的人进行对话。 你可以使用 GitHub Flavored Markdown 在任何地方评论特定的代码行、评论整个提交或评论整个拉取请求本身。

每次其他人评论拉取请求时,你都会继续收到电子邮件通知,因此你知道有活动发生。 每个通知都将包含指向拉取请求的链接,你也可以直接回复电子邮件以评论拉取请求线程。

Responses to emails are included in the thread
图 115. 对电子邮件的回复包含在线程中

一旦代码处于你喜欢的位置并想要将其合并,你可以将代码拉取下来并在本地合并,可以使用我们之前看到的 git pull <url> <branch> 语法,或者通过添加 fork 作为远程仓库并进行获取(fetch)和合并(merge)。

如果合并很简单,你也可以直接点击 GitHub 网站上的“Merge”(合并)按钮。 这将执行“非快进”合并,即使可以进行快进合并,也会创建一个合并提交。 这意味着无论如何,每次你点击合并按钮时,都会创建一个合并提交。 正如你在 合并按钮和手动合并拉取请求的说明 中看到的那样,如果你单击提示链接,GitHub 会为你提供所有这些信息。

Merge button and instructions for merging a Pull Request manually
图 116. 合并按钮和手动合并拉取请求的说明

如果你决定不合并它,你也可以直接关闭拉取请求,打开它的人会收到通知。

拉取请求引用

如果你要处理大量拉取请求,并且不想每次都添加一堆远程仓库或执行一次性拉取,GitHub 允许你执行一个巧妙的技巧。 这是一个有点高级的技巧,我们将在 Refspec 中更详细地介绍此技巧,但它可能非常有用。

实际上,GitHub 将存储库的拉取请求分支宣传为服务器上的一种伪分支。 默认情况下,克隆时你不会获得它们,但它们以一种模糊的方式存在,你可以很容易地访问它们。

为了演示这一点,我们将使用一个低级命令(通常称为“底层”命令,我们将在 底层和高级命令 中更多地了解它),称为 ls-remote。 此命令通常不用于日常 Git 操作,但它有助于向我们展示服务器上存在哪些引用。

如果我们针对我们之前使用的“blink”存储库运行此命令,我们将获得存储库中所有分支、标签和其他引用的列表。

$ git ls-remote https://github.com/schacon/blink
10d539600d86723087810ec636870a504f4fee4d	HEAD
10d539600d86723087810ec636870a504f4fee4d	refs/heads/master
6a83107c62950be9453aac297bb0193fd743cd6e	refs/pull/1/head
afe83c2d1a70674c9505cc1d8b7d380d5e076ed3	refs/pull/1/merge
3c8d735ee16296c242be7a9742ebfbc2665adec1	refs/pull/2/head
15c9f4f80973a2758462ab2066b6ad9fe8dcf03d	refs/pull/2/merge
a5a7751a33b7e86c5e9bb07b26001bb17d775d1a	refs/pull/4/head
31a45fc257e8433c8d8804e3e848cf61c9d3166c	refs/pull/4/merge

当然,如果你在你的存储库中并运行 git ls-remote origin 或你想检查的任何远程仓库,它将显示与此类似的内容。

如果存储库位于 GitHub 上并且你已打开任何拉取请求,你将获得这些以 refs/pull/ 开头的引用。 这些基本上是分支,但由于它们不在 refs/heads/ 下,因此你在从服务器克隆或获取时通常不会获得它们 —— 获取过程通常会忽略它们。

每个拉取请求有两个引用 —— 以 /head 结尾的引用指向与拉取请求分支中的最后一个提交完全相同的提交。 因此,如果有人在我们的存储库中打开一个拉取请求,并且他们的分支名为 bug-fix 并且它指向提交 a5a775,那么在我们的存储库中,我们将没有 bug-fix 分支(因为它在他们的 fork 中),但我们拥有指向 a5a775pull/<pr#>/head。 这意味着我们可以很容易地一次性拉取每个拉取请求分支,而无需添加一堆远程仓库。

现在,你可以执行直接获取引用的操作。

$ git fetch origin refs/pull/958/head
From https://github.com/libgit2/libgit2
 * branch            refs/pull/958/head -> FETCH_HEAD

这告诉 Git,“连接到 origin 远程仓库,并下载名为 refs/pull/958/head 的引用。” Git 很乐意服从,并下载构建该引用所需的一切,并将指向你想要的提交的指针放在 .git/FETCH_HEAD 下。 你可以用 git merge FETCH_HEAD 将其合并到你想要测试它的分支中,但该合并提交消息看起来有点奇怪。 此外,如果你正在审查大量拉取请求,这会变得很乏味。

还有一种方法可以获取所有拉取请求,并在每次连接到远程仓库时保持它们是最新的。 在你最喜欢的编辑器中打开 .git/config,然后查找 origin 远程仓库。 它应该看起来有点像这样

[remote "origin"]
    url = https://github.com/libgit2/libgit2
    fetch = +refs/heads/*:refs/remotes/origin/*

fetch = 开头的行是一个“refspec”。 这是一种将远程仓库上的名称与本地 .git 目录中的名称映射的方法。 这个特定的 refspec 告诉 Git,“远程仓库上位于 refs/heads 下的内容应位于我本地存储库中 refs/remotes/origin 下。” 你可以修改此部分以添加另一个 refspec

[remote "origin"]
    url = https://github.com/libgit2/libgit2.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    fetch = +refs/pull/*/head:refs/remotes/origin/pr/*

最后一行告诉 Git,“所有看起来像 refs/pull/123/head 的引用都应该像 refs/remotes/origin/pr/123 一样在本地存储。” 现在,如果你保存该文件并执行 git fetch

$ git fetch
# …
 * [new ref]         refs/pull/1/head -> origin/pr/1
 * [new ref]         refs/pull/2/head -> origin/pr/2
 * [new ref]         refs/pull/4/head -> origin/pr/4
# …

现在,所有的远程拉取请求都以与跟踪分支非常相似的引用在本地表示; 它们是只读的,并且在你执行获取时会更新。 这使得在本地尝试来自拉取请求的代码变得非常容易

$ git checkout pr/2
Checking out files: 100% (3769/3769), done.
Branch pr/2 set up to track remote branch pr/2 from origin.
Switched to a new branch 'pr/2'

眼尖的人会注意到 refspec 的远程部分末尾的 head。 GitHub 方面还有一个 refs/pull/#/merge 引用,它表示如果你按下站点上的“merge”按钮将产生的提交。 这可以让你在按下按钮之前测试合并。

对拉取请求的拉取请求

你不仅可以打开以 main 或 master 分支为目标的拉取请求,实际上你还可以打开以网络中任何分支为目标的拉取请求。 事实上,你甚至可以以另一个拉取请求为目标。

如果你看到一个拉取请求朝着正确的方向发展,并且你有一个依赖于它的更改的想法,或者你不确定这是一个好主意,或者你只是没有对目标分支的推送访问权限,你可以直接向其打开一个拉取请求。

当你去打开一个拉取请求时,页面顶部有一个框,用于指定你要请求拉取到的分支以及你要请求从中拉取的分支。 如果你点击该框右侧的“Edit”(编辑)按钮,你不仅可以更改分支,还可以更改 fork。

Manually change the Pull Request target fork and branch
图 117. 手动更改拉取请求目标 fork 和分支

在这里,你可以相当容易地指定将你的新分支合并到另一个拉取请求或项目的另一个 fork 中。

提及和通知

GitHub 还有一个非常不错的内置通知系统,当你对特定个人或团队有疑问或需要反馈时,它可以派上用场。

在任何评论中,你可以开始键入 @ 字符,它将开始自动完成项目中协作者或贡献者的姓名和用户名。

Start typing @ to mention someone
图 118. 开始键入 @ 以提及某人

你也可以提及不在下拉菜单中的用户,但自动补全器通常可以使其更快。

一旦你发布了一个带有用户提及的评论,该用户将会收到通知。这意味着这是一种将人们拉入对话的非常有效的方式,而不是让他们轮询。在 GitHub 上的 Pull Requests 中,人们经常会拉入他们团队或公司中的其他人来审查 Issue 或 Pull Request。

如果有人在 Pull Request 或 Issue 上被提及,他们将被“订阅”到它,并且会继续在任何时候发生活动时收到通知。如果你打开了它,如果你正在关注该存储库,或者如果你在某个事物上发表评论,你也将被订阅到某个事物。如果你不再希望收到通知,则页面上有一个“取消订阅”按钮,你可以单击该按钮以停止接收有关它的更新。

Unsubscribe from an Issue or Pull Request
图 119. 取消订阅 Issue 或 Pull Request

通知页面

当我们在这里提到关于 GitHub 的“通知”时,我们指的是 GitHub 尝试在你发生事件时与你联系的一种特定方式,你可以通过几种不同的方式配置它们。如果你从设置页面转到“通知中心”选项卡,你可以看到你拥有的一些选项。

Notification center options
图 120. 通知中心选项

有两个选择是通过“电子邮件”和“Web”接收通知,你可以选择两者中的任何一个、都不选择,或者两者都选择,用于你积极参与的事情以及你正在关注的存储库上的活动。

Web 通知

Web 通知仅存在于 GitHub 上,你只能在 GitHub 上检查它们。如果你在首选项中选择了此选项,并且为你触发了通知,你将在屏幕顶部的通知图标上看到一个小蓝点,如 通知中心 中所示。

Notification center
图 121. 通知中心

如果你单击它,你将看到你已收到通知的所有项目的列表,按项目分组。你可以通过单击左侧边栏中的名称来筛选特定项目的通知。你还可以通过单击任何通知旁边的复选标记图标来确认通知,或者通过单击组顶部的复选标记来确认项目中所有的通知。每个复选标记旁边还有一个静音按钮,你可以单击该按钮以不再接收有关该项目的任何进一步通知。

所有这些工具对于处理大量通知都非常有用。许多 GitHub 高级用户将简单地完全关闭电子邮件通知,并通过此屏幕管理他们的所有通知。

电子邮件通知

电子邮件通知是通过 GitHub 处理通知的另一种方式。如果你启用了此选项,你将收到每个通知的电子邮件。我们在 作为电子邮件通知发送的评论新 Pull Request 的电子邮件通知 中看到了示例。电子邮件也将被正确地线程化,如果你使用的是线程化电子邮件客户端,这将非常棒。

GitHub 发送给你的电子邮件的标头中还嵌入了相当数量的元数据,这对于设置自定义过滤器和规则非常有帮助。

例如,如果我们查看在 新 Pull Request 的电子邮件通知 中显示的发送给 Tony 的电子邮件的实际电子邮件标头,我们将看到以下发送的信息:

To: tonychacon/fade <fade@noreply.github.com>
Message-ID: <tonychacon/fade/pull/1@github.com>
Subject: [fade] Wait longer to see the dimming effect better (#1)
X-GitHub-Recipient: tonychacon
List-ID: tonychacon/fade <fade.tonychacon.github.com>
List-Archive: https://github.com/tonychacon/fade
List-Post: <mailto:reply+i-4XXX@reply.github.com>
List-Unsubscribe: <mailto:unsub+i-XXX@reply.github.com>,...
X-GitHub-Recipient-Address: tchacon@example.com

这里有一些有趣的事情。如果你想突出显示或重新路由到此特定项目甚至 Pull Request 的电子邮件,Message-ID 中的信息会以 <user>/<project>/<type>/<id> 格式为你提供所有数据。例如,如果这是一个 issue,则 <type> 字段将是“issues”而不是“pull”。

List-PostList-Unsubscribe 字段意味着,如果你有一个了解这些字段的邮件客户端,你可以轻松地发布到列表或从线程“取消订阅”。这与单击 Web 版本通知上的“静音”按钮或 Issue 或 Pull Request 页面上的“取消订阅”基本相同。

还值得注意的是,如果你同时启用了电子邮件和 Web 通知,并且你读取了电子邮件版本的通知,如果你允许在邮件客户端中使用图像,则 Web 版本也会被标记为已读。

特殊文件

GitHub 会注意到一些特殊文件,如果它们存在于你的存储库中。

README

第一个是 README 文件,它可以是 GitHub 识别为散文的几乎任何格式。例如,它可以是 READMEREADME.mdREADME.asciidoc 等。如果 GitHub 在你的源代码中看到一个 README 文件,它将在项目的登陆页面上呈现它。

许多团队使用此文件来保存可能对存储库或项目不熟悉的人的所有相关项目信息。这通常包括以下内容:

  • 该项目是做什么用的

  • 如何配置和安装它

  • 如何使用它或使其运行的示例

  • 该项目提供的许可证

  • 如何为其做出贡献

由于 GitHub 将呈现此文件,你可以在其中嵌入图像或链接,以增加易于理解性。

CONTRIBUTING

GitHub 识别的另一个特殊文件是 CONTRIBUTING 文件。如果你有一个名为 CONTRIBUTING 的文件,带有任何文件扩展名,GitHub 将在任何人开始打开 Pull Request 时显示 打开 Pull Request 时存在 CONTRIBUTING 文件

Opening a Pull Request when a CONTRIBUTING file exists
图 122. 打开 Pull Request 时存在 CONTRIBUTING 文件

这里的想法是你可以指定你想要或不想要发送到你的项目的 Pull Request 中的具体内容。这样,人们在打开 Pull Request 之前可能会实际阅读指南。

项目管理

通常,你可以对单个项目执行的管理操作不多,但有几个项目可能会引起你的兴趣。

更改默认分支

如果你使用“master”以外的分支作为你希望人们在其上打开 Pull Request 或默认看到的分支,你可以在存储库的设置页面中的“选项”选项卡下更改该分支。

Change the default branch for a project
图 123. 更改项目的默认分支

只需在下拉列表中更改默认分支,这将成为从那时起所有主要操作的默认设置,包括有人克隆存储库时默认签出的分支。

转移项目

如果你想将项目转移给 GitHub 中的另一个用户或组织,在你的存储库设置页面的同一个“选项”选项卡的底部有一个“转移所有权”选项,允许你执行此操作。

Transfer a project to another GitHub user or Organization
图 124. 将项目转移给另一个 GitHub 用户或组织

如果你要放弃一个项目并且有人想接管它,或者如果你的项目越来越大并且想将其移动到组织中,这将很有帮助。

这不仅将存储库及其所有观察者和星星移动到另一个地方,而且还设置了从你的 URL 到新地方的重定向。它还将重定向 Git 的克隆和获取,而不仅仅是 Web 请求。

scroll-to-top